int get_nearest_request_of_specified_downward(const request_type_t * const pool, int specified, request_type_t type) { for (int i = N_LENGTH_OF_TASK_POOL-1; i >=0; i--) { if ((get_request_type(pool + i, type) != 0) && (i <= specified)) { return i; } } puts("get_nearest_request_of_specified_downward: no valid return"); return -1; }
/**************************************************************************** * Function : soap_device_callback * * Parameters : * IN http_parser_t *parser : Parsed request received by the device * IN http_message_t* request : HTTP request * INOUT SOCKINFO *info : socket info * * Description : This is a callback called by minisever after receiving * the request from the control point. This function will start * processing the request. It calls handle_invoke_action to handle the * SOAP action * * Return : void * * Note : ****************************************************************************/ void soap_device_callback( IN http_parser_t * parser, IN http_message_t * request, INOUT SOCKINFO * info ) { int err_code; const char *err_str; memptr action_name; IXML_Document *xml_doc = NULL; // set default error err_code = SOAP_INVALID_ACTION; err_str = Soap_Invalid_Action; // validate: content-type == text/xml if( !has_xml_content_type( request ) ) { goto error_handler; } // type of request if( get_request_type( request, &action_name ) != 0 ) { goto error_handler; } // parse XML err_code = ixmlParseBufferEx( request->entity.buf, &xml_doc ); if( err_code != IXML_SUCCESS ) { if( err_code == IXML_INSUFFICIENT_MEMORY ) { err_code = UPNP_E_OUTOF_MEMORY; } else { err_code = SOAP_ACTION_FAILED; } err_str = "XML error"; goto error_handler; } if( action_name.length == 0 ) { // query var handle_query_variable( info, request, xml_doc ); } else { // invoke action handle_invoke_action( info, request, action_name, xml_doc ); } err_code = 0; // no error error_handler: ixmlDocument_free( xml_doc ); if( err_code != 0 ) { send_error_response( info, err_code, err_str, request ); } }
/*! * \brief This is a callback called by minisever after receiving the request * from the control point. This function will start processing the request. * It calls handle_invoke_action to handle the SOAP action. */ void soap_device_callback( int iface, /*! [in] Parsed request received by the device. */ http_parser_t *parser, /*! [in] HTTP request. */ http_message_t *request, /*! [in,out] Socket info. */ SOCKINFO *info) { int err_code; const char *err_str; memptr action_name; IXML_Document *xml_doc = NULL; /* set default error */ err_code = SOAP_INVALID_ACTION; err_str = Soap_Invalid_Action; /* validate: content-type == text/xml */ if (!has_xml_content_type(request)) goto error_handler; /* type of request */ if (get_request_type(request, &action_name) != 0) goto error_handler; /* parse XML */ err_code = ixmlParseBufferEx(request->entity.buf, &xml_doc); if (err_code != IXML_SUCCESS) { if (err_code == IXML_INSUFFICIENT_MEMORY) err_code = UPNP_E_OUTOF_MEMORY; else err_code = SOAP_ACTION_FAILED; err_str = "XML error"; goto error_handler; } if (action_name.length == 0) /* query var */ handle_query_variable(iface, info, request, xml_doc); else /* invoke action */ handle_invoke_action(iface, info, request, action_name, xml_doc); /* no error */ err_code = 0; error_handler: ixmlDocument_free(xml_doc); if (err_code != 0) send_error_response(info, err_code, err_str, request); return; parser = parser; }
int main(void) { /*init all the things*/ motors_init(PHASE_CORRECT, PRESCALE_8); uart_init(BAUD_CALC(9600)); sei(); adc_init(); wdt_init(WDTO_500MS); /********************/ go(0, 0); uart_putc(ACK); over_current_a = 0; over_current_b = 0; while (1) { current_a = analog_read(C_SENS_A); current_b = analog_read(C_SENS_B); req_t = get_request_type(); if (req_t == CURRENT_REQ) { write_current(current_a, current_b); } else if (req_t == MOTORS_SET) { read_motors(&speed_a, &speed_b); wdt_reset(); } //manage current sens #ifdef CURRENT_LIMIT if ((current_a < CURRENT_LIMIT) && (current_b < CURRENT_LIMIT)) { go(speed_a, speed_b); over_current_a = over_current_b = 0; } else { //overcurrent go(0, 0); uart_putc('!'); over_current_a = current_a - CURRENT_LIMIT; over_current_b = current_b - CURRENT_LIMIT; } #endif } return (0); }
u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart, u32 FileLength) { u16 status = STATUS_SUCCESS; u32 state; u16 handshake; struct pseudo_hdr *pseudo_header; u16 pseudo_header_len; long word_length; u16 request; u16 temp; u16 tempword; struct dsp_file_hdr *file_hdr; struct dsp_image_info *dsp_img_info = NULL; long requested_version; bool correct_version; struct drv_msg *mailbox_data; u16 *data = NULL; u16 *s_file = NULL; u8 *c_file = NULL; u8 *boot_end = NULL, *code_end = NULL; int image; long loader_code_address, loader_code_size = 0; long run_address = 0, run_size = 0; u32 templong; u32 image_chksum = 0; u16 dpram = 0; u8 *pbuffer; struct prov_record *pprov_record; struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net); DEBUG("Entered scram_dnldr...\n"); pft1000info->fcodeldr = 0; pft1000info->usbboot = 0; pft1000info->dspalive = 0xffff; // // Get version id of file, at first 4 bytes of file, for newer files. // state = STATE_START_DWNLD; file_hdr = (struct dsp_file_hdr *)pFileStart; ft1000_write_register(ft1000dev, 0x800, FT1000_REG_MAG_WATERMARK); s_file = (u16 *) (pFileStart + file_hdr->loader_offset); c_file = (u8 *) (pFileStart + file_hdr->loader_offset); boot_end = (u8 *) (pFileStart + file_hdr->loader_code_end); loader_code_address = file_hdr->loader_code_address; loader_code_size = file_hdr->loader_code_size; correct_version = FALSE; while ((status == STATUS_SUCCESS) && (state != STATE_DONE_FILE)) { switch (state) { case STATE_START_DWNLD: DEBUG("FT1000:STATE_START_DWNLD\n"); if (pft1000info->usbboot) handshake = get_handshake_usb(ft1000dev, HANDSHAKE_DSP_BL_READY); else handshake = get_handshake(ft1000dev, HANDSHAKE_DSP_BL_READY); if (handshake == HANDSHAKE_DSP_BL_READY) { DEBUG ("scram_dnldr: handshake is HANDSHAKE_DSP_BL_READY, call put_handshake(HANDSHAKE_DRIVER_READY)\n"); put_handshake(ft1000dev, HANDSHAKE_DRIVER_READY); } else { DEBUG ("FT1000:download:Download error: Handshake failed\n"); status = STATUS_FAILURE; } state = STATE_BOOT_DWNLD; break; case STATE_BOOT_DWNLD: DEBUG("FT1000:STATE_BOOT_DWNLD\n"); pft1000info->bootmode = 1; handshake = get_handshake(ft1000dev, HANDSHAKE_REQUEST); if (handshake == HANDSHAKE_REQUEST) { /* * Get type associated with the request. */ request = get_request_type(ft1000dev); switch (request) { case REQUEST_RUN_ADDRESS: DEBUG("FT1000:REQUEST_RUN_ADDRESS\n"); put_request_value(ft1000dev, loader_code_address); break; case REQUEST_CODE_LENGTH: DEBUG("FT1000:REQUEST_CODE_LENGTH\n"); put_request_value(ft1000dev, loader_code_size); break; case REQUEST_DONE_BL: DEBUG("FT1000:REQUEST_DONE_BL\n"); /* Reposition ptrs to beginning of code section */ s_file = (u16 *) (boot_end); c_file = (u8 *) (boot_end); //DEBUG("FT1000:download:s_file = 0x%8x\n", (int)s_file); //DEBUG("FT1000:download:c_file = 0x%8x\n", (int)c_file); state = STATE_CODE_DWNLD; pft1000info->fcodeldr = 1; break; case REQUEST_CODE_SEGMENT: //DEBUG("FT1000:REQUEST_CODE_SEGMENT\n"); word_length = get_request_value(ft1000dev); //DEBUG("FT1000:word_length = 0x%x\n", (int)word_length); //NdisMSleep (100); if (word_length > MAX_LENGTH) { DEBUG ("FT1000:download:Download error: Max length exceeded\n"); status = STATUS_FAILURE; break; } if ((word_length * 2 + c_file) > boot_end) { /* * Error, beyond boot code range. */ DEBUG ("FT1000:download:Download error: Requested len=%d exceeds BOOT code boundary.\n", (int)word_length); status = STATUS_FAILURE; break; } /* * Position ASIC DPRAM auto-increment pointer. */ dpram = (u16) DWNLD_MAG1_PS_HDR_LOC; if (word_length & 0x1) word_length++; word_length = word_length / 2; status = write_blk(ft1000dev, &s_file, &c_file, word_length); //DEBUG("write_blk returned %d\n", status); break; default: DEBUG ("FT1000:download:Download error: Bad request type=%d in BOOT download state.\n", request); status = STATUS_FAILURE; break; } if (pft1000info->usbboot) put_handshake_usb(ft1000dev, HANDSHAKE_RESPONSE); else put_handshake(ft1000dev, HANDSHAKE_RESPONSE); } else { DEBUG ("FT1000:download:Download error: Handshake failed\n"); status = STATUS_FAILURE; } break; case STATE_CODE_DWNLD: //DEBUG("FT1000:STATE_CODE_DWNLD\n"); pft1000info->bootmode = 0; if (pft1000info->usbboot) handshake = get_handshake_usb(ft1000dev, HANDSHAKE_REQUEST); else handshake = get_handshake(ft1000dev, HANDSHAKE_REQUEST); if (handshake == HANDSHAKE_REQUEST) { /* * Get type associated with the request. */ if (pft1000info->usbboot) request = get_request_type_usb(ft1000dev); else request = get_request_type(ft1000dev); switch (request) { case REQUEST_FILE_CHECKSUM: DEBUG ("FT1000:download:image_chksum = 0x%8x\n", image_chksum); put_request_value(ft1000dev, image_chksum); break; case REQUEST_RUN_ADDRESS: DEBUG ("FT1000:download: REQUEST_RUN_ADDRESS\n"); if (correct_version) { DEBUG ("FT1000:download:run_address = 0x%8x\n", (int)run_address); put_request_value(ft1000dev, run_address); } else { DEBUG ("FT1000:download:Download error: Got Run address request before image offset request.\n"); status = STATUS_FAILURE; break; } break; case REQUEST_CODE_LENGTH: DEBUG ("FT1000:download:REQUEST_CODE_LENGTH\n"); if (correct_version) { DEBUG ("FT1000:download:run_size = 0x%8x\n", (int)run_size); put_request_value(ft1000dev, run_size); } else { DEBUG ("FT1000:download:Download error: Got Size request before image offset request.\n"); status = STATUS_FAILURE; break; } break; case REQUEST_DONE_CL: pft1000info->usbboot = 3; /* Reposition ptrs to beginning of provisioning section */ s_file = (u16 *) (pFileStart + file_hdr->commands_offset); c_file = (u8 *) (pFileStart + file_hdr->commands_offset); state = STATE_DONE_DWNLD; break; case REQUEST_CODE_SEGMENT: //DEBUG("FT1000:download: REQUEST_CODE_SEGMENT - CODELOADER\n"); if (!correct_version) { DEBUG ("FT1000:download:Download error: Got Code Segment request before image offset request.\n"); status = STATUS_FAILURE; break; } word_length = get_request_value(ft1000dev); //DEBUG("FT1000:download:word_length = %d\n", (int)word_length); if (word_length > MAX_LENGTH) { DEBUG ("FT1000:download:Download error: Max length exceeded\n"); status = STATUS_FAILURE; break; } if ((word_length * 2 + c_file) > code_end) { /* * Error, beyond boot code range. */ DEBUG ("FT1000:download:Download error: Requested len=%d exceeds DSP code boundary.\n", (int)word_length); status = STATUS_FAILURE; break; } /* * Position ASIC DPRAM auto-increment pointer. */ dpram = (u16) DWNLD_MAG1_PS_HDR_LOC; if (word_length & 0x1) word_length++; word_length = word_length / 2; write_blk_fifo(ft1000dev, &s_file, &c_file, word_length); if (pft1000info->usbboot == 0) pft1000info->usbboot++; if (pft1000info->usbboot == 1) { tempword = 0; ft1000_write_dpram16(ft1000dev, DWNLD_MAG1_PS_HDR_LOC, tempword, 0); } break; case REQUEST_MAILBOX_DATA: DEBUG ("FT1000:download: REQUEST_MAILBOX_DATA\n"); // Convert length from byte count to word count. Make sure we round up. word_length = (long)(pft1000info->DSPInfoBlklen + 1) / 2; put_request_value(ft1000dev, word_length); mailbox_data = (struct drv_msg *)&(pft1000info-> DSPInfoBlk[0]); /* * Position ASIC DPRAM auto-increment pointer. */ data = (u16 *) & mailbox_data->data[0]; dpram = (u16) DWNLD_MAG1_PS_HDR_LOC; if (word_length & 0x1) word_length++; word_length = (word_length / 2); for (; word_length > 0; word_length--) { /* In words */ templong = *data++; templong |= (*data++ << 16); status = fix_ft1000_write_dpram32 (ft1000dev, dpram++, (u8 *) & templong); } break; case REQUEST_VERSION_INFO: DEBUG ("FT1000:download:REQUEST_VERSION_INFO\n"); word_length = file_hdr->version_data_size; put_request_value(ft1000dev, word_length); /* * Position ASIC DPRAM auto-increment pointer. */ s_file = (u16 *) (pFileStart + file_hdr-> version_data_offset); dpram = (u16) DWNLD_MAG1_PS_HDR_LOC; if (word_length & 0x1) word_length++; word_length = (word_length / 2); for (; word_length > 0; word_length--) { /* In words */ templong = ntohs(*s_file++); temp = ntohs(*s_file++); templong |= (temp << 16); status = fix_ft1000_write_dpram32 (ft1000dev, dpram++, (u8 *) & templong); } break; case REQUEST_CODE_BY_VERSION: DEBUG ("FT1000:download:REQUEST_CODE_BY_VERSION\n"); correct_version = FALSE; requested_version = get_request_value(ft1000dev); dsp_img_info = (struct dsp_image_info *)(pFileStart + sizeof (struct dsp_file_hdr)); for (image = 0; image < file_hdr->nDspImages; image++) { if (dsp_img_info->version == requested_version) { correct_version = TRUE; DEBUG ("FT1000:download: correct_version is TRUE\n"); s_file = (u16 *) (pFileStart + dsp_img_info-> begin_offset); c_file = (u8 *) (pFileStart + dsp_img_info-> begin_offset); code_end = (u8 *) (pFileStart + dsp_img_info-> end_offset); run_address = dsp_img_info-> run_address; run_size = dsp_img_info-> image_size; image_chksum = (u32) dsp_img_info-> checksum; break; } dsp_img_info++; } //end of for if (!correct_version) { /* * Error, beyond boot code range. */ DEBUG ("FT1000:download:Download error: Bad Version Request = 0x%x.\n", (int)requested_version); status = STATUS_FAILURE; break; } break; default: DEBUG ("FT1000:download:Download error: Bad request type=%d in CODE download state.\n", request); status = STATUS_FAILURE; break; } if (pft1000info->usbboot) put_handshake_usb(ft1000dev, HANDSHAKE_RESPONSE); else put_handshake(ft1000dev, HANDSHAKE_RESPONSE); } else { DEBUG ("FT1000:download:Download error: Handshake failed\n"); status = STATUS_FAILURE; } break; case STATE_DONE_DWNLD: DEBUG("FT1000:download:Code loader is done...\n"); state = STATE_SECTION_PROV; break; case STATE_SECTION_PROV: DEBUG("FT1000:download:STATE_SECTION_PROV\n"); pseudo_header = (struct pseudo_hdr *)c_file; if (pseudo_header->checksum == hdr_checksum(pseudo_header)) { if (pseudo_header->portdest != 0x80 /* Dsp OAM */ ) { state = STATE_DONE_PROV; break; } pseudo_header_len = ntohs(pseudo_header->length); /* Byte length for PROV records */ // Get buffer for provisioning data pbuffer = kmalloc((pseudo_header_len + sizeof(struct pseudo_hdr)), GFP_ATOMIC); if (pbuffer) { memcpy(pbuffer, (void *)c_file, (u32) (pseudo_header_len + sizeof(struct pseudo_hdr))); // link provisioning data pprov_record = kmalloc(sizeof(struct prov_record), GFP_ATOMIC); if (pprov_record) { pprov_record->pprov_data = pbuffer; list_add_tail(&pprov_record-> list, &pft1000info-> prov_list); // Move to next entry if available c_file = (u8 *) ((unsigned long) c_file + (u32) ((pseudo_header_len + 1) & 0xFFFFFFFE) + sizeof(struct pseudo_hdr)); if ((unsigned long)(c_file) - (unsigned long)(pFileStart) >= (unsigned long)FileLength) { state = STATE_DONE_FILE; } } else { kfree(pbuffer); status = STATUS_FAILURE; } } else { status = STATUS_FAILURE; } } else { /* Checksum did not compute */ status = STATUS_FAILURE; } DEBUG ("ft1000:download: after STATE_SECTION_PROV, state = %d, status= %d\n", state, status); break; case STATE_DONE_PROV: DEBUG("FT1000:download:STATE_DONE_PROV\n"); state = STATE_DONE_FILE; break; default: status = STATUS_FAILURE; break; } /* End Switch */ if (status != STATUS_SUCCESS) { break; } /**** // Check if Card is present status = Harley_Read_Register(&temp, FT1000_REG_SUP_IMASK); if ( (status != NDIS_STATUS_SUCCESS) || (temp == 0x0000) ) { break; } status = Harley_Read_Register(&temp, FT1000_REG_ASIC_ID); if ( (status != NDIS_STATUS_SUCCESS) || (temp == 0xffff) ) { break; } ****/ } /* End while */ DEBUG("Download exiting with status = 0x%8x\n", status); ft1000_write_register(ft1000dev, FT1000_DB_DNLD_TX, FT1000_REG_DOORBELL); return status; }
bool jdk_http_request_header::flatten( jdk_dynbuf &dest, bool full_url ) const { if( is_valid()) { jdk_str<4096> line; dest.clear(); if( get_request_type()==REQUEST_UNKNOWN ) { line.cpy( request_type_extended ); } else { line.cpy( http_methods[ get_request_type() ] ); line.cat( " " ); if( get_request_type()==REQUEST_CONNECT ) { jdk_str<256> hostport; hostport.form( "%s:%d", url.host.c_str(), url.port ); line.cat( hostport ); } else { if( full_url ) { line.cat( url.unexplode() ); } else { line.cat( url.path ); } } line.cat( " " ); line.cat( http_version ); line.cat( "\r\n" ); } dest.append_from_string( line ); int p = url.port; if( p==-1 ) p=80; if( p==80 ) { line.form( "Host: %s\r\n", url.host.c_str() ); } else { line.form( "Host: %s:%d\r\n", url.host.c_str(), p ); } dest.append_from_string( line ); // now append all other keys and values for( size_t i=0; i<map.count(); ++i ) { const pair_t *entry = map.get( i ); // is it a valid entry? if( entry ) { // create the line for this key value pair line.form( "%s %s\r\n", entry->key.c_str(), entry->value.c_str() ); // only append lines that arent just full of white space if( line.len()>3 ) { dest.append_from_string( line ); } } } // thats it, finish it off with a blank line dest.append_from_string( "\r\n" ); return true; } else { return false; } }
int test1(void) { puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */ print_request_pool(request_pool, N_FLOORS); set_request_type(request_pool + 5, request_call_cmd); set_request_type(request_pool + 13, request_call_cmd); set_request_type(request_pool + 0, request_call_cmd); print_request_pool(request_pool, N_FLOORS); clr_request_type(request_pool + 5, request_call_cmd); clr_request_type(request_pool + 13, request_call_down); set_request_type(request_pool + 0, request_call_up); print_request_pool(request_pool, N_FLOORS); for (int i = 0; i < 19; i++) { set_request_type(request_pool + i, request_call_up | request_call_down | request_call_cmd); printf("%d ", get_request_type(request_pool + i, request_call_up | request_call_cmd)); } puts(""); puts("udc"); print_request_pool(request_pool, N_FLOORS); for (int i = 0; i < 19; i++) { int j = get_nearest_request_of_specified_upward(request_pool2, i, request_call_up | request_call_down | request_call_cmd); printf("%d ", j); } puts(""); puts("u"); for (int i = 0; i < 19; i++) { int j = get_nearest_request_of_specified_upward(request_pool2, i, request_call_up); printf("%d ", j); } puts(""); puts("d"); for (int i = 0; i < 19; i++) { int j = get_nearest_request_of_specified_upward(request_pool2, i, request_call_down); printf("%d ", j); } puts(""); puts("c"); for (int i = 0; i < 19; i++) { int j = get_nearest_request_of_specified_upward(request_pool2, i, request_call_cmd); printf("%d ", j); } puts(""); puts("ud"); for (int i = 0; i < 19; i++) { int j = get_nearest_request_of_specified_upward(request_pool2, i, request_call_up | request_call_down); printf("%d ", j); } puts(""); puts("uc"); for (int i = 0; i < 19; i++) { int j = get_nearest_request_of_specified_upward(request_pool2, i, request_call_up | request_call_cmd); printf("%d ", j); } puts(""); puts("dc"); for (int i = 0; i < 19; i++) { int j = get_nearest_request_of_specified_upward(request_pool2, i, request_call_down | request_call_cmd); printf("%d ", j); } return EXIT_SUCCESS; }
/******** DOSTUFF() ********************* There is a separate instance of this function for each connection. It handles all communication once a connnection has been established. *****************************************/ void dostuff (int sock) { int n; char buffer[256]; bzero(buffer,256); n = read(sock,buffer,255); if (n < 0) error("ERROR reading from socket"); char* request_type = get_request_type(buffer); if (request_type == NULL) { printf("Bad request\n"); write(sock, "HTTP/1.1 400 Bad Request\n", 23); write(sock, "Connection: close\n\n", 19); write(sock, "400 Bad Request", 15); return; } if (strcmp(request_type, "GET")) { printf("Unsupported request type %s\n", request_type); write(sock, "HTTP/1.1 400 Bad Request\n", 23); write(sock, "Connection: close\n\n", 19); write(sock, "400 Bad Request", 15); return; } printf("Request type: %s\n", request_type); char* filename = parse_request(buffer); if (filename == NULL) { printf("Bad request\n"); write(sock, "HTTP/1.1 400 Bad Request\n", 23); write(sock, "Connection: close\n\n", 19); write(sock, "400 Bad Request", 15); return; } printf("Here is the message: %s\n",buffer); int f_size = get_filesize(filename); if (f_size == -1) { printf("Could not find file %s\n", filename); write(sock, "HTTP/1.1 404 Not Found\n", 23); write(sock, "Connection: close\n\n", 19); write(sock, "404 Not Found", 13); error("ERROR: Could not find file"); } n = write(sock, "HTTP/1.1 200 OK\n", 16); if (n < 0) error("ERROR writing to socket"); printf("Transfering file %s with length %d\n", filename, f_size); FILE* f = fopen(filename, "r"); char* file_data = (char *) malloc(sizeof(char) * f_size); fread(file_data, 1, f_size, f); n = write(sock, "Connection: close\n\n", 19); if (n < 0) error("ERROR writing to socket"); n = write(sock, file_data, f_size); if (n < 0) error("ERROR writing to socket"); printf("Done transfering file\n"); free(filename); free(file_data); fclose(f); return; }
bool send_request(struct server_data* server, const char* request, int request_length) { int socket_fd = get_client_socket_fd(); char ip_address_str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &server->address.sin_addr, ip_address_str, INET_ADDRSTRLEN); int port = ntohs(server->address.sin_port); char request_type_str[MTN_REQ_TYPE_LEN + 1]; get_request_type_str(request_type_str, get_request_type(request)); if(sendto(socket_fd, request, request_length, 0, (struct sockaddr *) &(server->address), sizeof(server->address)) == -1) { error_errno("cannot send %s request to %s:%d", request_type_str, ip_address_str, port); return false; } time_t send_time; if((send_time = time(NULL)) == -1) { fatal_error(1, "cannot measure time"); } info("Sending %s request to %s:%d", request_type_str, ip_address_str, port); struct timespec timeout; timeout.tv_sec = send_time + SERVER_RESPONSE_TIMEOUT; timeout.tv_nsec = 0; pthread_mutex_lock(&server->mutex); while(server->state != RESP) { if(pthread_cond_timedwait(&response_cond, &server->mutex, &timeout) == ETIMEDOUT) { info("Server %s:%d is not responding to %s request", ip_address_str, port, request_type_str); server->last_connect_attempt_time = send_time; server->not_connect_count++; if(server->not_connect_count % MAX_NOT_CONNECT_COUNT == 0) { // client runs out of attempts to connect to the server // client now waits for next attempt server->state = WAIT; } pthread_mutex_unlock(&server->mutex); return false; } } char response_type_str[MTN_RES_TYPE_LEN + 1]; get_response_type_str(response_type_str, get_response_type(server->response)); time_t connect_time; if((connect_time = time(NULL)) == -1) { fatal_error(1, "cannot measure time"); } info("Receiving %s response from %s:%d", response_type_str, ip_address_str, port); info("%s", server->response); server->last_connect_attempt_time = connect_time; server->not_connect_count = 0; pthread_mutex_unlock(&server->mutex); return true; }
void handle_request( std::string request_line, SocketCache& pushers, std::vector<Address>& routing_addresses, std::unordered_map<Key, std::unordered_set<Address>>& key_address_cache, unsigned& seed, std::shared_ptr<spdlog::logger> logger, UserThread& ut, zmq::socket_t& response_puller, zmq::socket_t& key_address_puller, Address& ip, unsigned& thread_id, unsigned& rid, unsigned& trial) { std::vector<std::string> v; split(request_line, ' ', v); Key key; std::string value; if (!((v.size() == 2 && v[0] == "GET") || (v.size() == 3 && v[0] == "PUT"))) { std::cerr << "Usage: GET <key> | PUT <key> <value>" << std::endl; return; } else { if (v[0] == "GET") { key = v[1]; value = ""; } else { key = v[1]; value = v[2]; } } if (trial > 5) { logger->info("Trial #{} for request for key {}.", trial, key); logger->info("Waiting 5 seconds."); std::chrono::seconds dura(5); std::this_thread::sleep_for(dura); logger->info("Waited 5s."); } // get worker address Address worker_address; if (key_address_cache.find(key) == key_address_cache.end()) { // query the routing and update the cache Address target_routing_address = kHashRingUtil ->get_random_routing_thread(routing_addresses, seed, kRoutingThreadCount) .get_key_address_connect_addr(); bool succeed; std::vector<Address> addresses = kHashRingUtil->get_address_from_routing( ut, key, pushers[target_routing_address], key_address_puller, succeed, ip, thread_id, rid); if (succeed) { for (const std::string& address : addresses) { key_address_cache[key].insert(address); } worker_address = addresses[rand_r(&seed) % addresses.size()]; } else { logger->error( "Request timed out when querying routing. This should never happen!"); return; } } else { if (key_address_cache[key].size() == 0) { logger->error("Address cache for key " + key + " has size 0."); return; } worker_address = *(next(begin(key_address_cache[key]), rand_r(&seed) % key_address_cache[key].size())); } KeyRequest req; req.set_response_address(ut.get_request_pulling_connect_addr()); std::string req_id = ip + ":" + std::to_string(thread_id) + "_" + std::to_string(rid); req.set_request_id(req_id); rid += 1; KeyTuple* tp = req.add_tuples(); tp->set_key(key); tp->set_address_cache_size(key_address_cache[key].size()); if (value == "") { // get request req.set_type(get_request_type("GET")); } else { // put request req.set_type(get_request_type("PUT")); tp->set_value(value); tp->set_timestamp(0); } bool succeed; auto res = send_request<KeyRequest, KeyResponse>(req, pushers[worker_address], response_puller, succeed); if (succeed) { KeyTuple tuple = res.tuples(0); // initialize the respond string if (tuple.error() == 2) { trial += 1; if (trial > 5) { for (const auto& address : res.tuples(0).addresses()) { logger->info("Server's return address for key {} is {}.", key, address); } for (const std::string& address : key_address_cache[key]) { logger->info("My cached address for key {} is {}", key, address); } } // update cache and retry key_address_cache.erase(key); handle_request(request_line, pushers, routing_addresses, key_address_cache, seed, logger, ut, response_puller, key_address_puller, ip, thread_id, rid, trial); } else { // succeeded if (tuple.has_invalidate() && tuple.invalidate()) { // update cache key_address_cache.erase(key); } if (value == "" && tuple.error() == 0) { std::cout << "value of key " + tuple.key() + " is " + tuple.value() + "\n"; } else if (value == "" && tuple.error() == 1) { std::cout << "key " + tuple.key() + " does not exist\n"; } else if (value != "") { std::cout << "successfully put key " + tuple.key() + "\n"; } } } else { logger->info( "Request timed out when querying worker: clearing cache due to " "possible node membership changes."); // likely the node has departed. We clear the entries relavant to the // worker_address std::vector<std::string> tokens; split(worker_address, ':', tokens); std::string signature = tokens[1]; std::unordered_set<Key> remove_set; for (const auto& key_pair : key_address_cache) { for (const std::string& address : key_pair.second) { std::vector<std::string> v; split(address, ':', v); if (v[1] == signature) { remove_set.insert(key_pair.first); } } } for (const std::string& key : remove_set) { key_address_cache.erase(key); } trial += 1; handle_request(request_line, pushers, routing_addresses, key_address_cache, seed, logger, ut, response_puller, key_address_puller, ip, thread_id, rid, trial); } }