test-server-status: increase tx size to avoid WRITEABLE loops
[platform/upstream/libwebsockets.git] / test-server / test-server-status.c
1 /*
2  * libwebsockets-test-server - libwebsockets test implementation
3  *
4  * Copyright (C) 2010-2016 Andy Green <andy@warmcat.com>
5  *
6  * This file is made available under the Creative Commons CC0 1.0
7  * Universal Public Domain Dedication.
8  *
9  * The person who associated a work with this deed has dedicated
10  * the work to the public domain by waiving all of his or her rights
11  * to the work worldwide under copyright law, including all related
12  * and neighboring rights, to the extent allowed by law. You can copy,
13  * modify, distribute and perform the work, even for commercial purposes,
14  * all without asking permission.
15  *
16  * The test apps are intended to be adapted for use in your code, which
17  * may be proprietary.  So unlike the library itself, they are licensed
18  * Public Domain.
19  */
20 #include "test-server.h"
21 #include <time.h>
22
23 static unsigned char server_info[1024];
24 static int server_info_len;
25 static int current;
26 static char cache[16384];
27 static int cache_len;
28 static struct per_session_data__lws_status *list;
29 static int live_wsi;
30
31
32 static void
33 update_status(struct lws *wsi, struct per_session_data__lws_status *pss)
34 {
35         struct per_session_data__lws_status **pp = &list;
36         int subsequent = 0;
37         char *p = cache + LWS_PRE, *start = p;
38         char date[128];
39         time_t t;
40         struct tm *ptm;
41 #ifndef WIN32
42         struct tm tm;
43 #endif
44
45         p += lws_snprintf(p, 512, " { %s, \"wsi\":\"%d\", \"conns\":[",
46                      server_info, live_wsi);
47
48         /* render the list */
49         while (*pp) {
50                 t = (*pp)->tv_established.tv_sec;
51 #ifdef WIN32
52                 ptm = localtime(&t);
53                 if (!ptm)
54 #else
55                 ptm = &tm;
56                 if (!localtime_r(&t, &tm))
57 #endif
58                         strcpy(date, "unknown");
59                 else
60 #ifdef WIN32
61                         strftime(date, sizeof(date), "%Y %H:%M %Z", ptm);
62 #else
63                         strftime(date, sizeof(date), "%F %H:%M %Z", ptm);
64 #endif
65                 if ((p - start) > (sizeof(cache) - 512))
66                         break;
67                 if (subsequent)
68                         *p++ = ',';
69                 subsequent = 1;
70                 p += lws_snprintf(p, sizeof(cache) - (p - start) - 1,
71                                 "{\"peer\":\"%s\",\"time\":\"%s\","
72                                 "\"ua\":\"%s\"}",
73                              (*pp)->ip, date, (*pp)->user_agent);
74                 pp = &((*pp)->list);
75         }
76
77         p += sprintf(p, "]}");
78         cache_len = p - start;
79         lwsl_err("cache_len %d\n", cache_len);
80         *p = '\0';
81
82         /* since we changed the list, increment the 'version' */
83         current++;
84         /* update everyone */
85         lws_callback_on_writable_all_protocol(lws_get_context(wsi),
86                                               lws_get_protocol(wsi));
87 }
88
89
90 /* lws-status protocol */
91
92 int
93 callback_lws_status(struct lws *wsi, enum lws_callback_reasons reason,
94                     void *user, void *in, size_t len)
95 {
96         struct per_session_data__lws_status *pss =
97                         (struct per_session_data__lws_status *)user,
98                         **pp;
99         char name[128], rip[128];
100         int m;
101
102         switch (reason) {
103
104         case LWS_CALLBACK_PROTOCOL_INIT:
105                 /*
106                  * Prepare the static server info
107                  */
108                 server_info_len = sprintf((char *)server_info,
109                                           "\"version\":\"%s\","
110                                           " \"hostname\":\"%s\"",
111                                           lws_get_library_version(),
112                                           lws_canonical_hostname(
113                                                         lws_get_context(wsi)));
114                 break;
115
116         case LWS_CALLBACK_ESTABLISHED:
117                 /*
118                  * we keep a linked list of live pss, so we can walk it
119                  */
120                 pss->last = 0;
121                 pss->list = list;
122                 list = pss;
123                 live_wsi++;
124                 lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name,
125                                        sizeof(name), rip, sizeof(rip));
126                 sprintf(pss->ip, "%s (%s)", name, rip);
127                 gettimeofday(&pss->tv_established, NULL);
128                 strcpy(pss->user_agent, "unknown");
129                 lws_hdr_copy(wsi, pss->user_agent, sizeof(pss->user_agent),
130                              WSI_TOKEN_HTTP_USER_AGENT);
131                 update_status(wsi, pss);
132                 break;
133
134         case LWS_CALLBACK_RECEIVE:
135                 lwsl_notice("pmd test: RX len %d\n", (int)len);
136                 puts(in);
137                 break;
138
139         case LWS_CALLBACK_SERVER_WRITEABLE:
140                 m = lws_write(wsi, (unsigned char *)cache + LWS_PRE, cache_len,
141                               LWS_WRITE_TEXT);
142                 if (m < server_info_len) {
143                         lwsl_err("ERROR %d writing to di socket\n", m);
144                         return -1;
145                 }
146                 break;
147
148         case LWS_CALLBACK_CLOSED:
149                 /*
150                  * remove ourselves from live pss list
151                  */
152                 lwsl_debug("CLOSING pss %p ********\n", pss);
153
154                 pp = &list;
155                 while (*pp) {
156                         if (*pp == pss) {
157                                 *pp = pss->list;
158                                 pss->list = NULL;
159                                 live_wsi--;
160                                 break;
161                         }
162                         pp = &((*pp)->list);
163                 }
164
165                 update_status(wsi, pss);
166                 break;
167
168         default:
169                 break;
170         }
171
172         return 0;
173 }