00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "libts.h"
00025 #include "P_Net.h"
00026 #include "Show.h"
00027 #include "I_Tasks.h"
00028
00029 struct ShowNet;
00030 typedef int (ShowNet::*ShowNetEventHandler) (int event, Event * data);
00031 struct ShowNet: public ShowCont
00032 {
00033 int ithread;
00034 IpEndpoint addr;
00035
00036 int showMain(int event, Event * e)
00037 {
00038 CHECK_SHOW(begin("Net"));
00039 CHECK_SHOW(show("<H3>Show <A HREF=\"./connections\">Connections</A></H3>\n"
00040
00041 "<form method = GET action = \"./ips\">\n"
00042 "Show Connections to/from IP (e.g. 127.0.0.1):<br>\n"
00043 "<input type=text name=ip size=64 maxlength=256>\n"
00044 "</form>\n"
00045 "<form method = GET action = \"./ports\">\n"
00046 "Show Connections to/from Port (e.g. 80):<br>\n"
00047 "<input type=text name=name size=64 maxlength=256>\n" "</form>\n"));
00048 return complete(event, e);
00049 }
00050
00051 int showConnectionsOnThread(int event, Event * e)
00052 {
00053 EThread *ethread = e->ethread;
00054 NetHandler *nh = get_NetHandler(ethread);
00055 MUTEX_TRY_LOCK(lock, nh->mutex, ethread);
00056 if (!lock) {
00057 ethread->schedule_in(this, NET_RETRY_DELAY);
00058 return EVENT_DONE;
00059 }
00060
00061 ink_hrtime now = ink_get_hrtime();
00062 forl_LL(UnixNetVConnection, vc, nh->open_list) {
00063
00064 if (ats_is_ip(&addr) && addr != vc->server_addr)
00065 continue;
00066
00067
00068 char ipbuf[INET6_ADDRSTRLEN];
00069 ats_ip_ntop(&vc->server_addr.sa, ipbuf, sizeof(ipbuf));
00070 char opt_ipbuf[INET6_ADDRSTRLEN];
00071 char interbuf[80];
00072 snprintf(interbuf, sizeof(interbuf), "[%s] %s:%d",
00073 vc->options.toString(vc->options.addr_binding),
00074 vc->options.local_ip.toString(opt_ipbuf, sizeof(opt_ipbuf)),
00075 vc->options.local_port
00076 );
00077 CHECK_SHOW(show("<tr>"
00078
00079 "<td>%d</td>"
00080 "<td>%s</td>"
00081 "<td>%d</td>"
00082 "<td>%d</td>"
00083 "<td>%s</td>"
00084
00085 "<td>%d secs ago</td>"
00086 "<td>%d</td>"
00087 "<td>%d</td>"
00088 "<td>%" PRId64 "</td>"
00089 "<td>%" PRId64 "</td>"
00090 "<td>%d</td>"
00091 "<td>%" PRId64 "</td>"
00092 "<td>%" PRId64 "</td>"
00093 "<td>%d secs</td>"
00094 "<td>%d secs</td>"
00095 "<td>%d</td>"
00096 "<td>-%s</td>"
00097 "</tr>\n",
00098 vc->id,
00099 ipbuf,
00100 ats_ip_port_host_order(&vc->server_addr),
00101 vc->con.fd,
00102 interbuf,
00103
00104 (int) ((now - vc->submit_time) / HRTIME_SECOND),
00105 ethread->id,
00106 vc->read.enabled,
00107 vc->read.vio.nbytes,
00108 vc->read.vio.ndone,
00109 vc->write.enabled,
00110 vc->write.vio.nbytes,
00111 vc->write.vio.ndone,
00112 (int) (vc->inactivity_timeout_in / HRTIME_SECOND),
00113 (int) (vc->active_timeout_in / HRTIME_SECOND), vc->f.shutdown, vc->closed ? "closed " : ""));
00114 }
00115 ithread++;
00116 if (ithread < eventProcessor.n_threads_for_type[ET_NET])
00117 eventProcessor.eventthread[ET_NET][ithread]->schedule_imm(this);
00118 else {
00119 CHECK_SHOW(show("</table>\n"));
00120 return complete(event, e);
00121 }
00122 return EVENT_CONT;
00123 }
00124
00125 int showConnections(int event, Event * e)
00126 {
00127 CHECK_SHOW(begin("Net Connections"));
00128 CHECK_SHOW(show("<H3>Connections</H3>\n"
00129 "<table border=1><tr>"
00130 "<th>ID</th>"
00131 "<th>IP</th>"
00132 "<th>Port</th>"
00133 "<th>FD</th>"
00134 "<th>Interface</th>"
00135 "<th>Accept Port</th>"
00136 "<th>Time Started</th>"
00137 "<th>Thread</th>"
00138 "<th>Read Enabled</th>"
00139 "<th>Read NBytes</th>"
00140 "<th>Read NDone</th>"
00141 "<th>Write Enabled</th>"
00142 "<th>Write NBytes</th>"
00143 "<th>Write NDone</th>"
00144 "<th>Inactive Timeout</th>"
00145 "<th>Active Timeout</th>"
00146 "<th>Shutdown</th>"
00147 "<th>Comments</th>"
00148 "</tr>\n"));
00149 SET_HANDLER(&ShowNet::showConnectionsOnThread);
00150 eventProcessor.eventthread[ET_NET][0]->schedule_imm(this);
00151 return EVENT_CONT;
00152 }
00153
00154 int showSingleThread(int event, Event * e)
00155 {
00156 EThread *ethread = e->ethread;
00157 NetHandler *nh = get_NetHandler(ethread);
00158 PollDescriptor *pollDescriptor = get_PollDescriptor(ethread);
00159 MUTEX_TRY_LOCK(lock, nh->mutex, ethread);
00160 if (!lock) {
00161 ethread->schedule_in(this, NET_RETRY_DELAY);
00162 return EVENT_DONE;
00163 }
00164
00165 CHECK_SHOW(show("<H3>Thread: %d</H3>\n", ithread));
00166 CHECK_SHOW(show("<table border=1>\n"));
00167 int connections = 0;
00168 forl_LL(UnixNetVConnection, vc, nh->open_list)
00169 connections++;
00170 CHECK_SHOW(show("<tr><td>%s</td><td>%d</td></tr>\n", "Connections", connections));
00171
00172 CHECK_SHOW(show("<tr><td>%s</td><td>%d</td></tr>\n", "Last Poll Ready", pollDescriptor->result));
00173 CHECK_SHOW(show("</table>\n"));
00174 CHECK_SHOW(show("<table border=1>\n"));
00175 CHECK_SHOW(show
00176 ("<tr><th>#</th><th>Read Priority</th><th>Read Bucket</th><th>Write Priority</th><th>Write Bucket</th></tr>\n"));
00177 CHECK_SHOW(show("</table>\n"));
00178 ithread++;
00179 if (ithread < eventProcessor.n_threads_for_type[ET_NET])
00180 eventProcessor.eventthread[ET_NET][ithread]->schedule_imm(this);
00181 else
00182 return complete(event, e);
00183 return EVENT_CONT;
00184 }
00185
00186 int showThreads(int event, Event * e)
00187 {
00188 CHECK_SHOW(begin("Net Threads"));
00189 SET_HANDLER(&ShowNet::showSingleThread);
00190 eventProcessor.eventthread[ET_NET][0]->schedule_imm(this);
00191 return EVENT_CONT;
00192 }
00193 int showSingleConnection(int event, Event * e)
00194 {
00195 CHECK_SHOW(begin("Net Connection"));
00196 return complete(event, e);
00197 }
00198 int showHostnames(int event, Event * e)
00199 {
00200 CHECK_SHOW(begin("Net Connections to/from Host"));
00201 return complete(event, e);
00202 }
00203
00204 ShowNet(Continuation * c, HTTPHdr * h):
00205 ShowCont(c, h), ithread(0) {
00206 memset(&addr, 0, sizeof(addr));
00207 SET_HANDLER(&ShowNet::showMain);
00208 }
00209 };
00210
00211 #undef STREQ_PREFIX
00212 #define STREQ_PREFIX(_x,_n,_s) (!ptr_len_ncasecmp(_x,_n,_s,sizeof(_s)-1))
00213 Action *
00214 register_ShowNet(Continuation * c, HTTPHdr * h)
00215 {
00216 ShowNet *s = new ShowNet(c, h);
00217 int path_len;
00218 const char *path = h->url_get()->path_get(&path_len);
00219
00220 SET_CONTINUATION_HANDLER(s, &ShowNet::showMain);
00221 if (STREQ_PREFIX(path, path_len, "connections")) {
00222 SET_CONTINUATION_HANDLER(s, &ShowNet::showConnections);
00223 } else if (STREQ_PREFIX(path, path_len, "threads")) {
00224 SET_CONTINUATION_HANDLER(s, &ShowNet::showThreads);
00225 } else if (STREQ_PREFIX(path, path_len, "ips")) {
00226 int query_len;
00227 const char *query = h->url_get()->query_get(&query_len);
00228 s->sarg = ats_strndup(query, query_len);
00229 char *gn = NULL;
00230 if (s->sarg)
00231 gn = (char *)memchr(s->sarg, '=', strlen(s->sarg));
00232 if (gn)
00233 ats_ip_pton(gn + 1, &s->addr);
00234 SET_CONTINUATION_HANDLER(s, &ShowNet::showConnections);
00235 } else if (STREQ_PREFIX(path, path_len, "ports")) {
00236 int query_len;
00237 const char *query = h->url_get()->query_get(&query_len);
00238 s->sarg = ats_strndup(query, query_len);
00239 char *gn = NULL;
00240 if (s->sarg)
00241 gn = (char *)memchr(s->sarg, '=', strlen(s->sarg));
00242 if (gn)
00243 ats_ip_port_cast(&s->addr.sa) = htons(atoi(gn+1));
00244 SET_CONTINUATION_HANDLER(s, &ShowNet::showConnections);
00245 }
00246 eventProcessor.schedule_imm(s, ET_TASK);
00247 return &s->action;
00248 }
00249