//Main function int main(int argc, char* argv[]) { //LIRC Variables struct lirc_config *config; //HTTP Variables char *host = "10.0.0.2"; char *http_request_format = "POST /php/remote_control_api.php HTTP/1.1\n" "Host: 10.0.0.2\n" "Content-Type: application/x-www-form-urlencoded\n" "Content-Length: 10\n\n" "function=%s\n"; char http_request[MAX_HTTP_REQUEST_LEN]; char http_response[MAX_HTTP_RESPONSE_LEN]; //Socket Variables int sockfd, error; struct addrinfo hints, *addrinfo_list, *addrinfo; //Misc Variables int valid_key = 0; struct timeval tv; gettimeofday(&tv, NULL); time_t start_time = tv.tv_sec, end_time, time_delay; //Outputs usage and exits if given more than one file path in arguments if (argc>2) { fprintf(stderr, "Usage: %s <config file>\n", argv[0]); return -1; } //Initializes LIRC and exits if unsuccessful, called at start of execution if (lirc_init("lirc",1)==-1) { fprintf(stderr, "lirc_init: failed to initialize lirc\n"); return -1; } //Clears hints structure and set appropriately for call to getaddrinfo() memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; //Gets the linked list of possible addrinfo structures if (error = getaddrinfo(host, PORT, &hints, &addrinfo_list) != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error)); return -1; } //Iterate through linked list of possible addrinfo structures and attempts to create socket to connect to for (addrinfo = addrinfo_list; addrinfo != NULL; addrinfo = addrinfo->ai_next) { //Creates a socket if ((sockfd = socket(addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol)) == -1) { continue; } //Connect to socket if (connect(sockfd, addrinfo->ai_addr, addrinfo->ai_addrlen) == -1) { close(sockfd); continue; } //Break out of loop if calls to socket() and connect() are both successful break; } //If none of the addrinfo structures in the linked list works, then exit program if (addrinfo == NULL) { fprintf(stderr, "failed to connect to %s\n", host); return -1; } fprintf(stdout, "connection to %s was successful\n\n", host); close(sockfd); //Read in configuration file from either argument or default path if (lirc_readconfig(argc==2 ? argv[1]:NULL, &config, NULL) == 0) { char *code; //Used to store the key code of the remote //Blocks the program until an IR signal is recieved from key press while (lirc_nextcode(&code)==0) { //Handle logic key press, if any if (code==NULL) continue; { gettimeofday(&tv, NULL); end_time = tv.tv_sec; printf("Starttime=%ld\tEndtime=%ld\n\n", start_time, end_time); if (end_time - start_time > DELAY) { //Clears request and response buffer memset(&http_request, 0, sizeof http_request); memset(&http_response, 0, sizeof http_response); if (strstr(code,"KEY_POWER")) { if ((valid_key = handle_key_power(http_request, http_request_format)) == -1) { return -1; } } else if (strstr(code,"KEY_STOP")) { if ((valid_key = handle_key_stop(http_request, http_request_format)) == -1) { return -1; } } else if (strstr(code,"KEY_PAUSE")) { if ((valid_key = handle_key_pause(http_request, http_request_format)) == -1) { return -1; } } else if (strstr(code,"KEY_PLAY")) { if ((valid_key = handle_key_play(http_request, http_request_format)) == -1) { return -1; } } else if (strstr(code,"KEY_REWIND")) { if ((valid_key = handle_key_rewind(http_request, http_request_format)) == -1) { return -1; } } else if (strstr(code,"KEY_FORWARD")) { if ((valid_key = handle_key_forward(http_request, http_request_format)) == -1) { return -1; } } if (valid_key) { //Creates socket if ((sockfd = socket(addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol)) == -1) { return -1; } //Connect to socket if (connect(sockfd, addrinfo->ai_addr, addrinfo->ai_addrlen) == -1) { close(sockfd); return -1; } if (send_http_request(sockfd, http_request) == -1) { fprintf(stderr, "An error has occur while sending the HTTP request\n"); } else { fprintf(stdout, "HTTP request has been sent successfully.\n" "--------------------------------------------------\n" "%s\n\n", http_request); } if (receive_http_response(sockfd, http_response) == -1) { fprintf(stderr, "An error has occur while receiving the HTTP response\n"); } else { fprintf(stdout, "HTTP response has been received successfully.\n" "--------------------------------------------------\n" "%s\n\n", http_response); } close(sockfd); } gettimeofday(&tv, NULL); start_time = tv.tv_sec; } } free(code); //Free allocated memory for code after key press is handled } lirc_freeconfig(config); //Free allocated memory for configuration structure } //Deallocate memory from linked list of addrinfo structures freeaddrinfo(addrinfo_list); lirc_deinit(); //Deinitializes LIRC, called at end of program execution return 0; //EXIT_SUCCESS } //end of main()
void rhizome_direct_http_dispatch(rhizome_direct_sync_request *r) { DEBUGF("Dispatch size_high=%lld",r->cursor->size_high); rhizome_direct_transport_state_http *state = r->transport_specific_state; int sock=socket(AF_INET, SOCK_STREAM, 0); if (sock==-1) { WHY_perror("socket"); goto end; } struct hostent *hostent; hostent = gethostbyname(state->host); if (!hostent) { DEBUGF("could not resolve hostname"); goto end; } struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(state->port); addr.sin_addr = *((struct in_addr *)hostent->h_addr); bzero(&(addr.sin_zero),8); if (connect(sock,(struct sockaddr *)&addr,sizeof(struct sockaddr)) == -1) { WHY_perror("connect"); close(sock); goto end; } char boundary[20]; char buffer[8192]; strbuf bb = strbuf_local(boundary, sizeof boundary); strbuf_sprintf(bb, "%08lx%08lx", random(), random()); assert(!strbuf_overrun(bb)); strbuf content_preamble = strbuf_alloca(200); strbuf content_postamble = strbuf_alloca(40); strbuf_sprintf(content_preamble, "--%s\r\n" "Content-Disposition: form-data; name=\"data\"; filename=\"IHAVEs\"\r\n" "Content-Type: application/octet-stream\r\n" "\r\n", boundary ); strbuf_sprintf(content_postamble, "\r\n--%s--\r\n", boundary); assert(!strbuf_overrun(content_preamble)); assert(!strbuf_overrun(content_postamble)); int content_length = strbuf_len(content_preamble) + r->cursor->buffer_offset_bytes + r->cursor->buffer_used + strbuf_len(content_postamble); strbuf request = strbuf_local(buffer, sizeof buffer); strbuf_sprintf(request, "POST /rhizome/enquiry HTTP/1.0\r\n" "Content-Length: %d\r\n" "Content-Type: multipart/form-data; boundary=%s\r\n" "\r\n%s", content_length, boundary, strbuf_str(content_preamble) ); assert(!strbuf_overrun(request)); /* TODO: Refactor this code so that it uses our asynchronous framework. */ int len = strbuf_len(request); int sent=0; while(sent<len) { DEBUGF("write(%d, %s, %d)", sock, alloca_toprint(-1, &buffer[sent], len-sent), len-sent); int count=write(sock,&buffer[sent],len-sent); if (count == -1) { if (errno==EPIPE) goto rx; WHYF_perror("write(%d)", len - sent); close(sock); goto end; } sent+=count; } len=r->cursor->buffer_offset_bytes+r->cursor->buffer_used; sent=0; while(sent<len) { int count=write(sock,&r->cursor->buffer[sent],len-sent); if (count == -1) { if (errno == EPIPE) goto rx; WHYF_perror("write(%d)", count); close(sock); goto end; } sent+=count; } strbuf_reset(request); strbuf_puts(request, strbuf_str(content_postamble)); len = strbuf_len(request); sent=0; while(sent<len) { DEBUGF("write(%d, %s, %d)", sock, alloca_toprint(-1, &buffer[sent], len-sent), len-sent); int count=write(sock,&buffer[sent],len-sent); if (count == -1) { if (errno==EPIPE) goto rx; WHYF_perror("write(%d)", len - sent); close(sock); goto end; } sent+=count; } struct http_response_parts parts; rx: /* request sent, now get response back. */ if (receive_http_response(sock, buffer, sizeof buffer, &parts) == -1) { close(sock); goto end; } /* For some reason the response data gets overwritten during a push, so we need to copy it, and use the copy instead. */ unsigned char *actionlist=alloca(parts.content_length); bcopy(parts.content_start, actionlist, parts.content_length); dump("response", actionlist, parts.content_length); /* We now have the list of (1+RHIZOME_BAR_PREFIX_BYTES)-byte records that indicate the list of BAR prefixes that differ between the two nodes. We can now action those which are relevant, i.e., based on whether we are pushing, pulling or synchronising (both). I am currently undecided as to whether it is cleaner to have some general rhizome direct function for doing that, or whether it just adds unnecessary complication, and the responses should just be handled in here. For now, I am just going to implement it in here, and we can generalise later. */ int i; for(i=10;i<content_length;i+=(1+RHIZOME_BAR_PREFIX_BYTES)) { int type=actionlist[i]; unsigned long long bid_prefix_ll=rhizome_bar_bidprefix_ll((unsigned char *)&actionlist[i+1]); DEBUGF("%s %016llx* @ 0x%x",type==1?"push":"pull",bid_prefix_ll,i); if (type==2&&r->pullP) { /* Need to fetch manifest. Once we have the manifest, then we can use our normal bundle fetch routines from rhizome_fetch.c Generate a request like: GET /rhizome/manifestbybar/<hex of bar> and add it to our list of HTTP fetch requests, then watch until the request is finished. That will give us the manifest. Then as noted above, we can use that to pull the file down using existing routines. */ if (!rhizome_fetch_request_manifest_by_prefix (&addr,&actionlist[i+1],RHIZOME_BAR_PREFIX_BYTES, 1 /* import, getting file if needed */)) { /* Fetching the manifest, and then using it to see if we want to fetch the file for import is all handled asynchronously, so just wait for it to finish. */ while(rhizome_file_fetch_queue_count) fd_poll(); } } else if (type==1&&r->pushP) { /* Form up the POST request to submit the appropriate bundle. */ /* Start by getting the manifest, which is the main thing we need, and also gives us the information we need for sending any associated file. */ rhizome_manifest *m=rhizome_direct_get_manifest(&actionlist[i+1], RHIZOME_BAR_PREFIX_BYTES); if (!m) { WHY("This should never happen. The manifest exists, but when I went looking for it, it doesn't appear to be there."); goto next_item; } /* Get filehash and size from manifest if present */ const char *id = rhizome_manifest_get(m, "id", NULL, 0); DEBUGF("bundle id = '%s'",id); const char *hash = rhizome_manifest_get(m, "filehash", NULL, 0); DEBUGF("bundle file hash = '%s'",hash); long long filesize = rhizome_manifest_get_ll(m, "filesize"); DEBUGF("file size = %lld",filesize); /* We now have everything we need to compose the POST request and send it. */ char *template="POST /rhizome/import HTTP/1.0\r\n"