/[svn]/liblscp/trunk/examples/server.c
ViewVC logotype

Diff of /liblscp/trunk/examples/server.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 132 by capela, Fri Jun 18 14:19:19 2004 UTC revision 146 by capela, Fri Jun 25 12:00:25 2004 UTC
# Line 22  Line 22 
22    
23  #include "server.h"  #include "server.h"
24    
25  #define LSCP_SERVER_RETRY   3           // Maximum number of unanswered PING retries.  #define LSCP_SERVER_SLEEP   30          // Period in seconds for watchdog wakeup (idle loop).
 #define LSCP_SERVER_SLEEP   30          // Period in seconds for watchdog wakeup.  
26    
27    
28  // Local prototypes.  // Local prototypes.
# Line 31  Line 30 
30  static lscp_connect_t  *_lscp_connect_create            (lscp_server_t *pServer, lscp_socket_t sock, struct sockaddr_in *pAddr, int cAddr);  static lscp_connect_t  *_lscp_connect_create            (lscp_server_t *pServer, lscp_socket_t sock, struct sockaddr_in *pAddr, int cAddr);
31  static lscp_status_t    _lscp_connect_destroy           (lscp_connect_t *pConnect);  static lscp_status_t    _lscp_connect_destroy           (lscp_connect_t *pConnect);
32  static lscp_status_t    _lscp_connect_recv              (lscp_connect_t *pConnect);  static lscp_status_t    _lscp_connect_recv              (lscp_connect_t *pConnect);
 static lscp_status_t    _lscp_connect_send              (lscp_connect_t *pConnect, const char *pchBuffer, int cchBuffer);  
 static lscp_status_t    _lscp_connect_ping              (lscp_connect_t *pConnect);  
33    
34  static void             _lscp_connect_list_append       (lscp_connect_list_t *pList, lscp_connect_t *pItem);  static void             _lscp_connect_list_append       (lscp_connect_list_t *pList, lscp_connect_t *pItem);
35  static void             _lscp_connect_list_remove       (lscp_connect_list_t *pList, lscp_connect_t *pItem);  static void             _lscp_connect_list_remove       (lscp_connect_list_t *pList, lscp_connect_t *pItem);
36  static void             _lscp_connect_list_remove_safe  (lscp_connect_list_t *pList, lscp_connect_t *pItem);  static void             _lscp_connect_list_remove_safe  (lscp_connect_list_t *pList, lscp_connect_t *pItem);
37  static void             _lscp_connect_list_free         (lscp_connect_list_t *pList);  static void             _lscp_connect_list_free         (lscp_connect_list_t *pList);
 static lscp_connect_t  *_lscp_connect_list_find_addr    (lscp_connect_list_t *pList, struct sockaddr_in *pAddr);  
38  static lscp_connect_t  *_lscp_connect_list_find_sock    (lscp_connect_list_t *pList, lscp_socket_t sock);  static lscp_connect_t  *_lscp_connect_list_find_sock    (lscp_connect_list_t *pList, lscp_socket_t sock);
39    
 static lscp_status_t    _lscp_server_evt_recv           (lscp_server_t *pServer);  
   
40  static void             _lscp_server_thread_proc        (lscp_server_t *pServer);  static void             _lscp_server_thread_proc        (lscp_server_t *pServer);
41  static void             _lscp_server_select_proc        (lscp_server_t *pServer);  static void             _lscp_server_select_proc        (lscp_server_t *pServer);
42    
43  static void             _lscp_server_cmd_proc           (void *pvServer);  static void             _lscp_server_agent_proc         (void *pvServer);
 static void             _lscp_server_evt_proc           (void *pvServer);  
   
 static void             _lscp_watchdog_scan             (lscp_server_t *pServer);  
   
 static void             _lscp_watchdog_proc             (void *pvServer);  
44    
 #if defined(WIN32)  
 #include <time.h>  
 #undef  gettimeofday  
 #define gettimeofday(p,n)  {(p)->tv_sec = (long) (clock() / CLOCKS_PER_SEC); (p)->tv_usec = 0;}  
 #else  
 #include <sys/time.h>  
 #endif  
45    
46  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
47  // Server-side client connection list methods.  // Server-side client connection list methods.
# Line 158  static void _lscp_connect_list_free ( ls Line 140  static void _lscp_connect_list_free ( ls
140  }  }
141    
142    
 static lscp_connect_t *_lscp_connect_list_find_addr ( lscp_connect_list_t *pList, struct sockaddr_in *pAddr )  
 {  
     int iPort = ntohs(pAddr->sin_port);  
     const char *pszAddr = inet_ntoa(pAddr->sin_addr);  
     lscp_connect_t *p;  
   
 //  fprintf(stderr, "_lscp_connect_list_find_addr: pList=%p addr=%s port=%d.\n", pList, inet_ntoa(pAddr->sin_addr), ntohs(pAddr->sin_port));  
   
     for (p = pList->first; p; p = p->next) {  
         if (iPort == p->port && strcmp(pszAddr, inet_ntoa(p->client.addr.sin_addr)) == 0)  
             return p;  
     }  
   
     return NULL;  
 }  
   
   
143  static lscp_connect_t *_lscp_connect_list_find_sock ( lscp_connect_list_t *pList, lscp_socket_t sock )  static lscp_connect_t *_lscp_connect_list_find_sock ( lscp_connect_list_t *pList, lscp_socket_t sock )
144  {  {
145      lscp_connect_t *p;      lscp_connect_t *p;
# Line 197  static void _lscp_connect_proc ( void *p Line 162  static void _lscp_connect_proc ( void *p
162      lscp_connect_t *pConnect = (lscp_connect_t *) pvConnect;      lscp_connect_t *pConnect = (lscp_connect_t *) pvConnect;
163      lscp_server_t  *pServer  = pConnect->server;      lscp_server_t  *pServer  = pConnect->server;
164    
165      while (pServer->cmd.iState && pConnect->client.iState) {      while (pServer->agent.iState && pConnect->client.iState) {
166          if (_lscp_connect_recv(pConnect) != LSCP_OK)          if (_lscp_connect_recv(pConnect) != LSCP_OK)
167              pConnect->client.iState = 0;              pConnect->client.iState = 0;
168      }      }
# Line 225  static lscp_connect_t *_lscp_connect_cre Line 190  static lscp_connect_t *_lscp_connect_cre
190      memset(pConnect, 0, sizeof(lscp_connect_t));      memset(pConnect, 0, sizeof(lscp_connect_t));
191    
192      pConnect->server = pServer;      pConnect->server = pServer;
193        pConnect->events = LSCP_EVENT_NONE;
194    
195  #ifdef DEBUG  #ifdef DEBUG
196      fprintf(stderr, "_lscp_connect_create: pConnect=%p: sock=%d addr=%s port=%d.\n", pConnect, sock, inet_ntoa(pAddr->sin_addr), ntohs(pAddr->sin_port));      fprintf(stderr, "_lscp_connect_create: pConnect=%p: sock=%d addr=%s port=%d.\n", pConnect, sock, inet_ntoa(pAddr->sin_addr), ntohs(pAddr->sin_port));
# Line 253  static lscp_status_t _lscp_connect_destr Line 219  static lscp_status_t _lscp_connect_destr
219    
220  #ifdef DEBUG  #ifdef DEBUG
221      fprintf(stderr, "_lscp_connect_destroy: pConnect=%p.\n", pConnect);      fprintf(stderr, "_lscp_connect_destroy: pConnect=%p.\n", pConnect);
222        fprintf(stderr, "<%p> sock=%d addr=%s port=%d events=0x%04x ...\n", pConnect,
223            pConnect->client.sock,
224            inet_ntoa(pConnect->client.addr.sin_addr),
225            ntohs(pConnect->client.addr.sin_port),
226            (int) pConnect->events
227        );
228  #endif  #endif
229    
230      lscp_socket_agent_free(&(pConnect->client));      lscp_socket_agent_free(&(pConnect->client));
231    
232      if (pConnect->sessid)  #ifdef DEBUG
233          free(pConnect->sessid);      fprintf(stderr, "<%p> Done.\n", pConnect);
234    #endif
235    
236      free(pConnect);      free(pConnect);
237    
# Line 290  lscp_status_t _lscp_connect_recv ( lscp_ Line 263  lscp_status_t _lscp_connect_recv ( lscp_
263  }  }
264    
265    
 static lscp_status_t _lscp_connect_send ( lscp_connect_t *pConnect, const char *pchBuffer, int cchBuffer )  
 {  
     lscp_status_t ret = LSCP_FAILED;  
     struct sockaddr_in addr;  
     int cAddr;  
   
     if (pConnect == NULL)  
         return ret;  
     if (pchBuffer == NULL || cchBuffer < 1)  
         return ret;  
     if (pConnect->port == 0)  
         return ret;  
   
     cAddr = sizeof(struct sockaddr_in);  
     memcpy((char *) &addr, (char *) &(pConnect->client.addr), cAddr);  
     addr.sin_port = htons((short) pConnect->port);  
   
     if (sendto((pConnect->server)->evt.sock, pchBuffer, cchBuffer, 0, (struct sockaddr *) &addr, cAddr) == cchBuffer)  
         ret = LSCP_OK;  
     else  
         lscp_socket_perror("_lscp_connect_send: sendto");  
   
     return ret;  
 }  
   
   
 static lscp_status_t _lscp_connect_ping ( lscp_connect_t *pConnect )  
 {  
     char szBuffer[LSCP_BUFSIZ];  
   
     if (pConnect == NULL)  
         return LSCP_FAILED;  
     if (pConnect->sessid == NULL)  
         return LSCP_FAILED;  
   
 #ifdef DEBUG  
     fprintf(stderr, "_lscp_connect_ping: pConnect=%p: addr=%s port=%d sessid=%s.\n", pConnect, inet_ntoa(pConnect->client.addr.sin_addr), pConnect->port, pConnect->sessid);  
 #endif  
   
     sprintf(szBuffer, "PING %d %s\r\n", ntohs((pConnect->server)->evt.addr.sin_port), pConnect->sessid);  
   
     return _lscp_connect_send(pConnect, szBuffer, strlen(szBuffer));  
 }  
   
   
266  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
267  // Command service (stream oriented).  // Command service (stream oriented).
268    
 static lscp_status_t _lscp_server_evt_recv ( lscp_server_t *pServer )  
 {  
     lscp_status_t ret = LSCP_FAILED;  
     struct sockaddr_in addr;  
     int  cAddr;  
     char achBuffer[LSCP_BUFSIZ];  
     int  cchBuffer;  
     lscp_connect_t *pConnect;  
   
     cAddr = sizeof(addr);  
     cchBuffer = recvfrom(pServer->evt.sock, achBuffer, sizeof(achBuffer), 0, (struct sockaddr *) &addr, &cAddr);  
     if (cchBuffer > 0) {  
 #ifdef DEBUG  
         lscp_socket_trace("_lscp_server_evt_recv: recvfrom", &addr, achBuffer, cchBuffer);  
 #endif  
         // Just do a simple check for PONG events (ignore sessid).  
         if (strncmp(achBuffer, "PONG ", 5) == 0) {  
             pConnect = _lscp_connect_list_find_addr(&(pServer->connects), &addr);  
             if (pConnect)  
                 pConnect->ping = 0;  
         }  
         ret = LSCP_OK;  
     }  
     else lscp_socket_perror("_lscp_server_evt_recv: recvfrom");  
   
     return ret;  
 }  
   
   
269  static void _lscp_server_thread_proc ( lscp_server_t *pServer )  static void _lscp_server_thread_proc ( lscp_server_t *pServer )
270  {  {
271      lscp_socket_t sock;      lscp_socket_t sock;
# Line 378  static void _lscp_server_thread_proc ( l Line 277  static void _lscp_server_thread_proc ( l
277      fprintf(stderr, "_lscp_server_thread_proc: Server listening for connections.\n");      fprintf(stderr, "_lscp_server_thread_proc: Server listening for connections.\n");
278  #endif  #endif
279    
280      while (pServer->cmd.iState) {      while (pServer->agent.iState) {
281          cAddr = sizeof(struct sockaddr_in);          cAddr = sizeof(struct sockaddr_in);
282          sock = accept(pServer->cmd.sock, (struct sockaddr *) &addr, &cAddr);          sock = accept(pServer->agent.sock, (struct sockaddr *) &addr, &cAddr);
283          if (sock == INVALID_SOCKET) {          if (sock == INVALID_SOCKET) {
284              lscp_socket_perror("_lscp_server_thread_proc: accept");              lscp_socket_perror("_lscp_server_thread_proc: accept");
285              pServer->cmd.iState = 0;              pServer->agent.iState = 0;
286          } else {          } else {
287              pConnect = _lscp_connect_create(pServer, sock, &addr, cAddr);              pConnect = _lscp_connect_create(pServer, sock, &addr, cAddr);
288              if (pConnect) {              if (pConnect) {
# Line 407  static void _lscp_server_select_proc ( l Line 306  static void _lscp_server_select_proc ( l
306      struct timeval tv;  // For specifying a timeout value.      struct timeval tv;  // For specifying a timeout value.
307      int iSelect;        // Holds select return status.      int iSelect;        // Holds select return status.
308    
     struct timeval tv1, tv2;    // To compute delta timeouts.  
   
309      lscp_socket_t sock;      lscp_socket_t sock;
310      struct sockaddr_in addr;      struct sockaddr_in addr;
311      int cAddr;      int cAddr;
# Line 420  static void _lscp_server_select_proc ( l Line 317  static void _lscp_server_select_proc ( l
317      FD_ZERO(&master_fds);      FD_ZERO(&master_fds);
318      FD_ZERO(&select_fds);      FD_ZERO(&select_fds);
319    
320      // Add the listeners to the master set      // Add the listener to the master set
321      FD_SET((unsigned int) pServer->cmd.sock, &master_fds);      FD_SET((unsigned int) pServer->agent.sock, &master_fds);
     FD_SET((unsigned int) pServer->evt.sock, &master_fds);  
322    
323      // Keep track of the biggest file descriptor;      // Keep track of the biggest file descriptor;
324      // So far, it's ourself, the listener.      // So far, it's ourself, the listener.
325      if ((int) pServer->evt.sock > (int) pServer->cmd.sock)      fdmax = (int) pServer->agent.sock;
         fdmax = (int) pServer->evt.sock;  
     else  
         fdmax = (int) pServer->cmd.sock;  
   
     // To start counting for regular watchdog simulation.  
     gettimeofday(&tv1, NULL);  
     gettimeofday(&tv2, NULL);  
326    
327      // Main loop...      // Main loop...
328      while (pServer->cmd.iState) {      while (pServer->agent.iState) {
329    
330          // Use a copy of the master.          // Use a copy of the master.
331          select_fds = master_fds;          select_fds = master_fds;
332          // Use the timeout feature for watchdoggin.          // Use the timeout feature for watchdoggin.
333          tv.tv_sec = LSCP_SERVER_SLEEP - (tv2.tv_sec - tv1.tv_sec);          tv.tv_sec = LSCP_SERVER_SLEEP;
334          tv.tv_usec = 0;          tv.tv_usec = 0;
335          // Wait for events...          // Wait for events...
336          iSelect = select(fdmax + 1, &select_fds, NULL, NULL, &tv);          iSelect = select(fdmax + 1, &select_fds, NULL, NULL, &tv);
337    
         // Check later id it's time for ping time...  
         gettimeofday(&tv2, NULL);  
   
338          if (iSelect < 0) {          if (iSelect < 0) {
339              lscp_socket_perror("_lscp_server_select_proc: select");              lscp_socket_perror("_lscp_server_select_proc: select");
340              pServer->cmd.iState = 0;              pServer->agent.iState = 0;
341          }          }
342          else if (iSelect > 0) {          else if (iSelect > 0) {
343              // Run through the existing connections looking for data to read...              // Run through the existing connections looking for data to read...
344              for (fd = 0; fd < fdmax + 1; fd++) {              for (fd = 0; fd < fdmax + 1; fd++) {
345                  if (FD_ISSET(fd, &select_fds)) {    // We got one!!                  if (FD_ISSET(fd, &select_fds)) {    // We got one!!
346                      // Is it ourselves, the command listener?                      // Is it ourselves, the command listener?
347                      if (fd == (int) pServer->cmd.sock) {                      if (fd == (int) pServer->agent.sock) {
348                          // Accept the connection...                          // Accept the connection...
349                          cAddr = sizeof(struct sockaddr_in);                          cAddr = sizeof(struct sockaddr_in);
350                          sock = accept(pServer->cmd.sock, (struct sockaddr *) &addr, &cAddr);                          sock = accept(pServer->agent.sock, (struct sockaddr *) &addr, &cAddr);
351                          if (sock == INVALID_SOCKET) {                          if (sock == INVALID_SOCKET) {
352                              lscp_socket_perror("_lscp_server_select_proc: accept");                              lscp_socket_perror("_lscp_server_select_proc: accept");
353                              pServer->cmd.iState = 0;                              pServer->agent.iState = 0;
354                          } else {                          } else {
355                              // Add to master set.                              // Add to master set.
356                              FD_SET((unsigned int) sock, &master_fds);                              FD_SET((unsigned int) sock, &master_fds);
# Line 479  static void _lscp_server_select_proc ( l Line 365  static void _lscp_server_select_proc ( l
365                              }                              }
366                          }                          }
367                          // Done with one new connection.                          // Done with one new connection.
                     } else if (fd == (int) pServer->evt.sock) {  
                         // Or from the event listener?  
                         if (_lscp_server_evt_recv(pServer) != LSCP_OK)  
                             pServer->cmd.iState = 0;  
                         // Done with event transaction.  
368                      } else {                      } else {
369                          // Otherwise it's trivial transaction...                          // Otherwise it's trivial transaction...
370                          lscp_mutex_lock(pServer->connects.mutex);                          lscp_mutex_lock(pServer->connects.mutex);
# Line 506  static void _lscp_server_select_proc ( l Line 387  static void _lscp_server_select_proc ( l
387              }              }
388              // Done (iSelect > 0)              // Done (iSelect > 0)
389          }          }
   
         // Maybe select has timed out?  
         if (iSelect == 0 || (tv2.tv_sec - tv1.tv_sec > LSCP_SERVER_SLEEP)) {  
             // Let the pseudo-watchdog do it's stuff...  
             _lscp_watchdog_scan(pServer);  
             // Make it a new start...  
             gettimeofday(&tv1, NULL);  
         }  
390      }      }
391    
392  #ifdef DEBUG  #ifdef DEBUG
# Line 522  static void _lscp_server_select_proc ( l Line 395  static void _lscp_server_select_proc ( l
395  }  }
396    
397    
398  static void _lscp_server_cmd_proc ( void *pvServer )  static void _lscp_server_agent_proc ( void *pvServer )
399  {  {
400      lscp_server_t *pServer = (lscp_server_t *) pvServer;      lscp_server_t *pServer = (lscp_server_t *) pvServer;
401    
# Line 534  static void _lscp_server_cmd_proc ( void Line 407  static void _lscp_server_cmd_proc ( void
407    
408    
409  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
 // Event service (datagram oriented).  
   
 static void _lscp_server_evt_proc ( void *pvServer )  
 {  
     lscp_server_t *pServer = (lscp_server_t *) pvServer;  
   
 #ifdef DEBUG  
     fprintf(stderr, "_lscp_server_evt_proc: Server waiting for events.\n");  
 #endif  
   
     while (pServer->evt.iState) {  
         if (_lscp_server_evt_recv(pServer) != LSCP_OK)  
             pServer->evt.iState = 0;  
     }  
   
 #ifdef DEBUG  
     fprintf(stderr, "_lscp_server_evt_proc: Server closing.\n");  
 #endif  
 }  
   
   
 //-------------------------------------------------------------------------  
 // Watchdog thread procedure loop.  
   
 static void _lscp_watchdog_scan ( lscp_server_t *pServer )  
 {  
     lscp_connect_t *p, *pNext;  
   
     lscp_mutex_lock(pServer->connects.mutex);  
   
     for (p = pServer->connects.first; p; p = pNext) {  
         pNext = p->next;  
         if (p->port > 0) {  
             if (p->ping >= LSCP_SERVER_RETRY) {  
                 fprintf(stderr, "_lscp_watchdog_scan: addr=%s port=%d: Zombie connection about to close.\n", inet_ntoa(p->client.addr.sin_addr), ntohs(p->client.addr.sin_port));  
                 _lscp_connect_list_remove(&(pServer->connects), p);  
                 _lscp_connect_destroy(p);  
             } else {  
                 p->ping++;  
                 _lscp_connect_ping(p);  
             }  
         }  
     }  
   
     lscp_mutex_unlock(pServer->connects.mutex);  
 }  
   
   
 static void _lscp_watchdog_proc ( void *pvServer )  
 {  
     lscp_server_t *pServer = (lscp_server_t *) pvServer;  
   
 #ifdef DEBUG  
     fprintf(stderr, "_lscp_watchdog_proc: Watchdog thread started.\n");  
 #endif  
   
     while (pServer->iWatchdog) {  
   
 #if defined(WIN32)  
         Sleep(pServer->iSleep * 1000);  
 #else  
         sleep(pServer->iSleep);  
 #endif  
         _lscp_watchdog_scan(pServer);  
     }  
   
 #ifdef DEBUG  
     fprintf(stderr, "_lscp_watchdog_proc: Watchdog thread terminated.\n");  
 #endif  
 }  
   
   
 //-------------------------------------------------------------------------  
410  // Server versioning teller fuunction.  // Server versioning teller fuunction.
411    
412  /** Retrieve the current server library version string. */  /** Retrieve the current server library version string. */
# Line 696  lscp_server_t* lscp_server_create_ex ( i Line 496  lscp_server_t* lscp_server_create_ex ( i
496    
497      sock = socket(AF_INET, SOCK_STREAM, 0);      sock = socket(AF_INET, SOCK_STREAM, 0);
498      if (sock == INVALID_SOCKET) {      if (sock == INVALID_SOCKET) {
499          lscp_socket_perror("lscp_server_create: cmd: socket");          lscp_socket_perror("lscp_server_create: socket");
500          free(pServer);          free(pServer);
501          return NULL;          return NULL;
502      }      }
503    
504      if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)      if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
505          lscp_socket_perror("lscp_server_create: cmd: setsockopt(SO_REUSEADDR)");          lscp_socket_perror("lscp_server_create: setsockopt(SO_REUSEADDR)");
506  #if defined(WIN32)  #if defined(WIN32)
507      if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)      if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
508          lscp_socket_perror("lscp_server_create: cmd: setsockopt(SO_DONTLINGER)");          lscp_socket_perror("lscp_server_create: setsockopt(SO_DONTLINGER)");
509  #endif  #endif
510    
511  #ifdef DEBUG  #ifdef DEBUG
512      lscp_socket_getopts("lscp_server_create: cmd", sock);      lscp_socket_getopts("lscp_server_create", sock);
513  #endif  #endif
514    
515      cAddr = sizeof(struct sockaddr_in);      cAddr = sizeof(struct sockaddr_in);
# Line 719  lscp_server_t* lscp_server_create_ex ( i Line 519  lscp_server_t* lscp_server_create_ex ( i
519      addr.sin_port = htons((short) iPort);      addr.sin_port = htons((short) iPort);
520    
521      if (bind(sock, (const struct sockaddr *) &addr, cAddr) == SOCKET_ERROR) {      if (bind(sock, (const struct sockaddr *) &addr, cAddr) == SOCKET_ERROR) {
522          lscp_socket_perror("lscp_server_create: cmd: bind");          lscp_socket_perror("lscp_server_create: bind");
523          closesocket(sock);          closesocket(sock);
524          free(pServer);          free(pServer);
525          return NULL;          return NULL;
526      }      }
527    
528      if (listen(sock, 10) == SOCKET_ERROR) {      if (listen(sock, 10) == SOCKET_ERROR) {
529          lscp_socket_perror("lscp_server_create: cmd: listen");          lscp_socket_perror("lscp_server_create: listen");
530          closesocket(sock);          closesocket(sock);
531          free(pServer);          free(pServer);
532          return NULL;          return NULL;
# Line 734  lscp_server_t* lscp_server_create_ex ( i Line 534  lscp_server_t* lscp_server_create_ex ( i
534    
535      if (iPort == 0) {      if (iPort == 0) {
536          if (getsockname(sock, (struct sockaddr *) &addr, &cAddr) == SOCKET_ERROR) {          if (getsockname(sock, (struct sockaddr *) &addr, &cAddr) == SOCKET_ERROR) {
537              lscp_socket_perror("lscp_server_create: cmd: getsockname");              lscp_socket_perror("lscp_server_create: getsockname");
538              closesocket(sock);              closesocket(sock);
539              free(pServer);              free(pServer);
540          }          }
         // Make command and event ports equal?  
         iPort = ntohs(addr.sin_port);  
     }  
   
     lscp_socket_agent_init(&(pServer->cmd), sock, &addr, cAddr);  
   
 #ifdef DEBUG  
     fprintf(stderr, "lscp_server_create: cmd: sock=%d addr=%s port=%d.\n", pServer->cmd.sock, inet_ntoa(pServer->cmd.addr.sin_addr), ntohs(pServer->cmd.addr.sin_port));  
 #endif  
   
     // Prepare the event datagram server socket...  
   
     sock = socket(AF_INET, SOCK_DGRAM, 0);  
     if (sock == INVALID_SOCKET) {  
         lscp_socket_perror("lscp_server_create: evt: socket");  
         lscp_socket_agent_free(&(pServer->cmd));  
         free(pServer);  
         return NULL;  
541      }      }
542    
543      if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)      lscp_socket_agent_init(&(pServer->agent), sock, &addr, cAddr);
         lscp_socket_perror("lscp_server_create: evt: setsockopt(SO_REUSEADDR)");  
544    
545  #ifdef DEBUG  #ifdef DEBUG
546      lscp_socket_getopts("lscp_server_create: evt", sock);      fprintf(stderr, "lscp_server_create: sock=%d addr=%s port=%d.\n", pServer->agent.sock, inet_ntoa(pServer->agent.addr.sin_addr), ntohs(pServer->agent.addr.sin_port));
 #endif  
   
     cAddr = sizeof(struct sockaddr_in);  
     memset((char *) &addr, 0, cAddr);  
     addr.sin_family = AF_INET;  
     addr.sin_addr.s_addr = htonl(INADDR_ANY);  
     addr.sin_port = htons((short) iPort);  
   
     if (bind(sock, (const struct sockaddr *) &addr, cAddr) == SOCKET_ERROR) {  
         lscp_socket_perror("lscp_server_create: evt: bind");  
         lscp_socket_agent_free(&(pServer->cmd));  
         closesocket(sock);  
         free(pServer);  
         return NULL;  
     }  
   
     if (iPort == 0) {  
         if (getsockname(sock, (struct sockaddr *) &addr, &cAddr) == SOCKET_ERROR) {  
             lscp_socket_perror("lscp_server_create: evt: getsockname");  
             lscp_socket_agent_free(&(pServer->cmd));  
             closesocket(sock);  
             free(pServer);  
             return NULL;  
         }  
     }  
   
     lscp_socket_agent_init(&(pServer->evt), sock, &addr, cAddr);  
   
 #ifdef DEBUG  
     fprintf(stderr, "lscp_server_create: evt: sock=%d addr=%s port=%d.\n", pServer->evt.sock, inet_ntoa(pServer->evt.addr.sin_addr), ntohs(pServer->evt.addr.sin_port));  
547  #endif  #endif
548    
549      // Now's finally time to startup threads...      // Now's finally time to startup threads...
550    
551      // Command service thread...      // Command service thread...
552      if (lscp_socket_agent_start(&(pServer->cmd), _lscp_server_cmd_proc, pServer, 0) != LSCP_OK) {      if (lscp_socket_agent_start(&(pServer->agent), _lscp_server_agent_proc, pServer, 0) != LSCP_OK) {
553          lscp_socket_agent_free(&(pServer->cmd));          lscp_socket_agent_free(&(pServer->agent));
         lscp_socket_agent_free(&(pServer->evt));  
554          free(pServer);          free(pServer);
555          return NULL;          return NULL;
556      }      }
557    
     if (pServer->mode == LSCP_SERVER_THREAD) {  
         // Event service thread...  
         if (lscp_socket_agent_start(&(pServer->evt), _lscp_server_evt_proc, pServer, 0) != LSCP_OK) {  
             lscp_socket_agent_free(&(pServer->cmd));  
             lscp_socket_agent_free(&(pServer->evt));  
             free(pServer);  
             return NULL;  
         }  
         // Watchdog thread...  
         pServer->iWatchdog = 1;  
         pServer->iSleep    = LSCP_SERVER_SLEEP;  
         pServer->pWatchdog = lscp_thread_create(_lscp_watchdog_proc, pServer, 0);  
     }  
   
558      // Finally we've some success...      // Finally we've some success...
559      return pServer;      return pServer;
560  }  }
# Line 838  lscp_status_t lscp_server_join ( lscp_se Line 574  lscp_status_t lscp_server_join ( lscp_se
574      fprintf(stderr, "lscp_server_join: pServer=%p.\n", pServer);      fprintf(stderr, "lscp_server_join: pServer=%p.\n", pServer);
575  #endif  #endif
576    
577  //  if (pServer->mode == LSCP_SERVER_THREAD) {      lscp_socket_agent_join(&(pServer->agent));
 //      lscp_thread_join(pServer->pWatchdog);  
 //      lscp_socket_agent_join(&(pServer->evt));  
 //  }  
     lscp_socket_agent_join(&(pServer->cmd));  
578    
579      return LSCP_OK;      return LSCP_OK;
580  }  }
# Line 862  lscp_status_t lscp_server_destroy ( lscp Line 594  lscp_status_t lscp_server_destroy ( lscp
594      fprintf(stderr, "lscp_server_destroy: pServer=%p.\n", pServer);      fprintf(stderr, "lscp_server_destroy: pServer=%p.\n", pServer);
595  #endif  #endif
596    
     if (pServer->mode == LSCP_SERVER_THREAD) {  
         pServer->iWatchdog = 0;  
         lscp_thread_destroy(pServer->pWatchdog);  
     }  
     lscp_socket_agent_free(&(pServer->evt));  
     lscp_socket_agent_free(&(pServer->cmd));  
597      _lscp_connect_list_free(&(pServer->connects));      _lscp_connect_list_free(&(pServer->connects));
598        lscp_socket_agent_free(&(pServer->agent));
599    
600      free(pServer);      free(pServer);
601    
# Line 877  lscp_status_t lscp_server_destroy ( lscp Line 604  lscp_status_t lscp_server_destroy ( lscp
604    
605    
606  /**  /**
607   *  Send an event message to all subscribed clients.   *  Send an event notification message to all subscribed clients.
608   *   *
609   *  @param pServer      Pointer to server instance structure.   *  @param pServer      Pointer to server instance structure.
610   *  @param pchBuffer    Pointer to data to be sent to all clients.   *  @param event        Event type flag to send to all subscribed clients.
611   *  @param cchBuffer    Length of the data to be sent in bytes.   *  @param pchBuffer    Pointer to event data to be sent to all clients.
612     *  @param cchBuffer    Length of the event data to be sent in bytes.
613   *   *
614   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
615   */   */
616  lscp_status_t lscp_server_broadcast ( lscp_server_t *pServer, const char *pchBuffer, int cchBuffer )  lscp_status_t lscp_server_broadcast ( lscp_server_t *pServer, lscp_event_t event, const char *pchData, int cchData )
617  {  {
618      lscp_connect_t *p;      lscp_connect_t *p;
619        const char *pszEvent;
620        char  achBuffer[LSCP_BUFSIZ];
621        int   cchBuffer;
622    
623      if (pServer == NULL)      if (pServer == NULL)
624          return LSCP_FAILED;          return LSCP_FAILED;
625      if (pchBuffer == NULL || cchBuffer < 1)      if (pchData == NULL || cchData < 1)
626            return LSCP_FAILED;
627    
628        // Which (single) event?
629        pszEvent = lscp_event_to_text(event);
630        if (pszEvent == NULL)
631          return LSCP_FAILED;          return LSCP_FAILED;
632    
633        // Build the event message string...
634        cchBuffer = sprintf(achBuffer, "NOTIFY:%s:", pszEvent);
635        if (pchData) {
636            if (cchData > LSCP_BUFSIZ - cchBuffer - 2)
637                cchData = LSCP_BUFSIZ - cchBuffer - 2;
638            strncpy(&achBuffer[cchBuffer], pchData, cchData);
639            cchBuffer += cchData;
640        }
641        achBuffer[cchBuffer++] = '\r';
642        achBuffer[cchBuffer++] = '\n';
643    
644        // And do the direct broadcasting...
645        
646      lscp_mutex_lock(pServer->connects.mutex);      lscp_mutex_lock(pServer->connects.mutex);
647    
648      for (p = pServer->connects.first; p; p = p->next) {      for (p = pServer->connects.first; p; p = p->next) {
649          if (p->port > 0 && p->ping == 0)          if (p->events & event)
650              _lscp_connect_send(p, pchBuffer, cchBuffer);              send(p->client.sock, achBuffer, cchBuffer, 0);
651      }      }
652    
653      lscp_mutex_unlock(pServer->connects.mutex);      lscp_mutex_unlock(pServer->connects.mutex);
# Line 938  lscp_status_t lscp_server_result ( lscp_ Line 687  lscp_status_t lscp_server_result ( lscp_
687   *  Register client as a subscriber of event broadcast messages.   *  Register client as a subscriber of event broadcast messages.
688   *   *
689   *  @param pConnect Pointer to client connection instance structure.   *  @param pConnect Pointer to client connection instance structure.
690   *  @param iPort    UDP port number of the requesting client connection.   *  @param event    Event type flag of the requesting client subscription.
691   *   *
692   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
693   */   */
694  lscp_status_t lscp_server_subscribe ( lscp_connect_t *pConnect, int iPort )  lscp_status_t lscp_server_subscribe ( lscp_connect_t *pConnect, lscp_event_t event )
695  {  {
     char szSessID[32];  
   
696      if (pConnect == NULL)      if (pConnect == NULL)
697          return LSCP_FAILED;          return LSCP_FAILED;
698      if (iPort == 0 || pConnect->port > 0 || pConnect->sessid)      if (event == LSCP_EVENT_NONE)
699          return LSCP_FAILED;          return LSCP_FAILED;
700    
701      // Generate a psudo-unique session-id.      pConnect->events |= event;
     sprintf(szSessID, "%08x", ((unsigned int) pConnect->server << 8) ^ (unsigned int) pConnect);  
   
     pConnect->port = iPort;  
     pConnect->ping = 0;  
     pConnect->sessid = strdup(szSessID);  
702    
703      return _lscp_connect_ping(pConnect);      return LSCP_OK;
704  }  }
705    
706    
707  /**  /**
708   *  Deregister client as subscriber of event broadcast messages.   *  Deregister client as subscriber of event broadcast messages.
709   *   *
710   *  @param pConnect     Pointer to client connection instance structure.   *  @param pConnect Pointer to client connection instance structure.
711   *  @param pszSessID    Session identifier of the requesting client connection.   *  @param event    Event type flag of the requesting client unsubscription.
712   *   *
713   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
714  */  */
715  lscp_status_t lscp_server_unsubscribe ( lscp_connect_t *pConnect, const char *pszSessID )  lscp_status_t lscp_server_unsubscribe ( lscp_connect_t *pConnect, lscp_event_t event )
716  {  {
717      if (pConnect == NULL)      if (pConnect == NULL)
718          return LSCP_FAILED;          return LSCP_FAILED;
719      if (pConnect->port == 0 || pConnect->sessid == NULL)      if (event == LSCP_EVENT_NONE)
         return LSCP_FAILED;  
   
     // Session ids must match.  
     if (strcmp(pszSessID, pConnect->sessid) != 0)  
720          return LSCP_FAILED;          return LSCP_FAILED;
721    
722      free(pConnect->sessid);      pConnect->events &= ~event;
     pConnect->sessid = NULL;  
     pConnect->ping = 0;  
     pConnect->port = 0;  
723    
724      return LSCP_OK;      return LSCP_OK;
725  }  }

Legend:
Removed from v.132  
changed lines
  Added in v.146

  ViewVC Help
Powered by ViewVC