static int parse_from_memory(VBUCKET_CONFIG_HANDLE handle, const char *data) { int ret; cJSON *c = cJSON_Parse(data); if (c == NULL) { handle->errmsg = strdup("Failed to parse data. Invalid JSON?"); return -1; } ret = parse_cjson(handle, c); cJSON_Delete(c); return ret; }
VBUCKET_CONFIG_HANDLE vbucket_config_parse_string(const char *data) { VBUCKET_CONFIG_HANDLE vb; cJSON *c = cJSON_Parse(data); if (c == NULL) { errstr = "Failed to parse data"; return NULL; } vb = parse_cjson(c); cJSON_Delete(c); return vb; }
int daemon_mode(char *hostname, char* port) { char buf[MAXDATASIZE]; // For sending and receiving socket messages char *ptr1, *ptr2; int i; int rc; fd_set fds; // Socket Filedescriptor set char *jgaddr; // Group address char *juaddr; char *jbrand; char *jval; char *ok; char *gname; // Name int gtype; // ---------------- FOR DAEMON USE, OPEN SOCKETS --------------------------------- // If we choose daemon mode, we will need to open a socket for communication // This needs to be done BEFORE enabling the interrupt handler, as we want // the handler to send its code to the LamPI-daemon process // Open a socket if ((sockfd = open_socket(hostname,port)) < 0) { fprintf(stderr,"Error opening socket for host %s. Exiting program\n\n", hostname); exit (1); }; FD_ZERO(&fds); FD_SET(sockfd, &fds); // The command below is sort of initialization command to put the sender in // a known state. Without it, there might be a proble when more than one Raspberry is // used for transmitting on the network. Unitialized it will apparently send noise ... // XXX Maybe just pulling the transmitter pin to 0 will work as well :-) send_2_device("kaku", "99", "1", "on"); for (;;) { // If we run a daemon, the interrupt handler outputs to the LamPI-daemon directly // so this program ONLY needs to sleep in that case to save cpu cycles // if (verbose == 1) { printf("daemon_mode: transaction: %d, sleep: %d, sockerr: %d, stop_ints: %d\n", socktcnt, SLEEP, sockerr, stop_ints); fflush (stdout); } // Is the socket still alive? XXX we should not always do this once we are here, // but only once in every 60 seconds or so .... if (verbose == 1) printf("PING\n"); sprintf(buf,"%d,PING",++socktcnt); // Keep_Alive and check for connection if (write(sockfd, buf, strlen(buf)) == -1) { perror("Error writing to socket\n"); close(sockfd); sleep(1); // Allow socket to close down // // If reconnecting failed due to LamPI-daemon not running, we have to wait until // the daemon is restarted by cron after 60 secs and restart again. // The easiest way is to quit the program and let it be restarted by cron too // XXX better way is loop and try a few times i=0; while ( ((sockfd = open_socket(hostname,port)) < 0) && (i++ < 15) ) { fprintf(stderr,"Error opening socket connection to daemon %s, retry: %d",hostname,i); sleep(5); } if (sockfd < 0) { fprintf(stderr,"Giving up: Error opening socket for host %s\n", hostname); exit(1); }; if (verbose==1) printf("daemon_mode:: reopened the socket\n"); // New socket created, hopefully we're fine now } // Now we have a connection still or again ... FD_ZERO(&fds); FD_SET(sockfd, &fds); timeout.tv_usec= 0; timeout.tv_sec = SLEEP; // Check for incoming socket messages. As longs as there is a message, read it, process it // If there are no fds ready, function returns 0, and we restart the loop while ((rc = select(sockfd+1, &fds, NULL, NULL, &timeout)) > 0) { // Look at the filedescriptor, and see if this socket is selected if (FD_ISSET(sockfd, &fds)) { if (verbose==1) printf("daemon_mode:: Message ready waiting on socket\n"); rc = read(sockfd, buf, MAXDATASIZE); if (rc == 0) { // Read error, break and establish new connection if necessary // If we break, we will automatically do a PING to check if (verbose == 1) printf("daemon_mode:: read error, connection lost?\n"); close(sockfd); break; } buf[rc]=0; // Terminate a string printf("Buf read:: <%s>\n",buf); ptr1 = buf; cJSON *root; for (;;) { root = cJSON_ParseWithOpts((const char*) ptr1,(const char **)&ptr2,0); // ptr contains end pos of parsed buf if (root == 0) { fprintf(stderr,"daemon_mode:: cJSON_ParseWithOps returned error\n"); // If the parsing failed, it COULD be that we did miss part of the message // we can read another message and concatenate it to the end of this message // However, more likely that we receive a non-JSON message. So discard the message for the moment cJSON_Delete(root); break; } ok = parse_cjson(root, "action"); // My ad-on parsing function if ((ok != NULL) && (strcmp(ok,"ack") == 0)) { goto next; } // Ignore OK messages for the receiver jbrand = parse_cjson(root, "brand"); // My ad-on parsing function if (jbrand == NULL) { printf("parse_cjson jbrand returned NULL \n"); goto next; } jgaddr = parse_cjson(root, "gaddr"); if (jgaddr == NULL) { printf("parse_cjson gaddr returned NULL \n"); goto next; } juaddr = parse_cjson(root, "uaddr"); if (juaddr == NULL) { printf("parse_cjson uaddr returned NULL \n"); goto next; } jval = parse_cjson(root, "val"); if (jval == NULL) { printf("parse_cjson val returned NULL \n"); goto next; } printf("Json:: gaddr: %s, uaddr: %s, val: %s\n",jgaddr, juaddr, jval); // Now transmit the command to a device using function transmit // if (dtransmit(jbrand, jgaddr, juaddr, jval) == -1) { printf("transmit: returned error \n"); continue; } next: cJSON_Delete(root); // We know now that we parsed a JSON message. If there are more JSON messages // in the buffer, we will have to parse them as well. So move the ppointers in buf // and loop again. if ((ptr2 - buf) < rc) { // printf("daemon_mode:: Unparsed data in buf: %d chars, first char: %c\n",(buf+rc-ptr2), *ptr2); ptr1 = ptr2; ptr2 = NULL; } else { break; } }//for }// FD_ISSET }// while if (rc == -1) perror("select failed with value -1"); if (rc == 0) { // perror("select failed with value 0"); // XXX Remove, val 0 means no data } stop_ints=0; continue; // Next loop }// for return(1); }