void i2p_stream::read_line(error_code const& e, boost::shared_ptr<handler_type> h) { TORRENT_ASSERT(m_magic == 0x1337); #if defined TORRENT_ASIO_DEBUGGING complete_async("i2p_stream::read_line"); #endif if (handle_error(e, h)) return; int read_pos = m_buffer.size(); // look for \n which means end of the response if (m_buffer[read_pos - 1] != '\n') { #if defined TORRENT_ASIO_DEBUGGING add_outstanding_async("i2p_stream::read_line"); #endif // read another byte from the socket m_buffer.resize(read_pos + 1); async_read(m_sock, boost::asio::buffer(&m_buffer[read_pos], 1) , boost::bind(&i2p_stream::read_line, this, _1, h)); return; } m_buffer[read_pos - 1] = 0; if (m_command == cmd_incoming) { // this is the line containing the destination // of the incoming connection in an accept call m_dest = &m_buffer[0]; (*h)(e); std::vector<char>().swap(m_buffer); return; } error_code invalid_response(i2p_error::parse_failed , get_i2p_category()); // null-terminate the string and parse it m_buffer.push_back(0); char* ptr = &m_buffer[0]; char* next = ptr; char const* expect1 = 0; char const* expect2 = 0; switch (m_state) { case read_hello_response: expect1 = "HELLO"; expect2 = "REPLY"; break; case read_connect_response: case read_accept_response: expect1 = "STREAM"; expect2 = "STATUS"; break; case read_session_create_response: expect1 = "SESSION"; expect2 = "STATUS"; break; case read_name_lookup_response: expect1 = "NAMING"; expect2 = "REPLY"; break; } // fprintf(stderr, "<<< %s\n", &m_buffer[0]); ptr = string_tokenize(next, ' ', &next); if (ptr == 0 || expect1 == 0 || strcmp(expect1, ptr)) { handle_error(invalid_response, h); return; } ptr = string_tokenize(next, ' ', &next); if (ptr == 0 || expect2 == 0 || strcmp(expect2, ptr)) { handle_error(invalid_response, h); return; } int result = 0; // char const* message = 0; // float version = 3.0f; for(;;) { char* name = string_tokenize(next, '=', &next); if (name == 0) break; // fprintf(stderr, "name=\"%s\"\n", name); char* ptr2 = string_tokenize(next, ' ', &next); if (ptr2 == 0) { handle_error(invalid_response, h); return; } // fprintf(stderr, "value=\"%s\"\n", ptr2); if (strcmp("RESULT", name) == 0) { if (strcmp("OK", ptr2) == 0) result = i2p_error::no_error; else if (strcmp("CANT_REACH_PEER", ptr2) == 0) result = i2p_error::cant_reach_peer; else if (strcmp("I2P_ERROR", ptr2) == 0) result = i2p_error::i2p_error; else if (strcmp("INVALID_KEY", ptr2) == 0) result = i2p_error::invalid_key; else if (strcmp("INVALID_ID", ptr2) == 0) result = i2p_error::invalid_id; else if (strcmp("TIMEOUT", ptr2) == 0) result = i2p_error::timeout; else if (strcmp("KEY_NOT_FOUND", ptr2) == 0) result = i2p_error::key_not_found; else if (strcmp("DUPLICATED_ID", ptr2) == 0) result = i2p_error::duplicated_id; else result = i2p_error::num_errors; // unknown error } else if (strcmp("MESSAGE", name) == 0) { // message = ptr2; } else if (strcmp("VERSION", name) == 0) { // version = float(atof(ptr2)); } else if (strcmp("VALUE", name) == 0) { m_name_lookup = ptr2; } else if (strcmp("DESTINATION", name) == 0) { m_dest = ptr2; } } error_code ec(result, get_i2p_category()); switch (result) { case i2p_error::no_error: case i2p_error::invalid_key: break; default: { handle_error (ec, h); return; } } switch (m_state) { case read_hello_response: switch (m_command) { case cmd_create_session: send_session_create(h); break; case cmd_accept: send_accept(h); break; case cmd_connect: send_connect(h); break; default: (*h)(e); std::vector<char>().swap(m_buffer); } break; case read_connect_response: case read_session_create_response: case read_name_lookup_response: (*h)(ec); std::vector<char>().swap(m_buffer); break; case read_accept_response: // the SAM bridge is waiting for an incoming // connection. // wait for one more line containing // the destination of the remote peer m_command = cmd_incoming; m_buffer.resize(1); #if defined TORRENT_ASIO_DEBUGGING add_outstanding_async("i2p_stream::read_line"); #endif async_read(m_sock, boost::asio::buffer(m_buffer) , boost::bind(&i2p_stream::read_line, this, _1, h)); break; } return; }
void vTaskVCP(void *pvParameters) { static u32 address = 0; static uint8_t usb_inited = 0; uint8_t c; int arg; uint8_t tmpbuf[EERROM_SIZE]; for(;;) { //Give the change to the OS scheduling. It is really a fool idea. Change me! //TODO - should use semaphore vTaskDelay( 1 / portTICK_RATE_MS ); // xSemaphoreTake(onVCPSemaphore, portMAX_DELAY); if(usb_inited == 0) { GPIO_InitTypeDef gpio; //This is a trick to perform a USB re-enumerate gpio.GPIO_Pin = GPIO_Pin_12; gpio.GPIO_Speed = GPIO_Speed_100MHz; gpio.GPIO_Mode = GPIO_Mode_OUT; gpio.GPIO_OType = GPIO_OType_PP; gpio.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOB, &gpio); GPIO_SetBits(GPIOB, GPIO_Pin_12 ); vTaskDelay(500 / portTICK_RATE_MS); GPIO_ResetBits(GPIOB, GPIO_Pin_12 ); // Initialize USB VCP. Do it ASAP USBD_Init(&USB_OTG_dev, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_CDC_cb, &USR_cb); usb_inited = 1; } if (VCP_get_char(&c)) { switch(c) { case PROTO_GET_SYNC: if (cin_wait(usb_vcp_timeout) != PROTO_EOC) goto cmd_bad; break; case PROTO_GET_DEVICE: arg = cin_wait(usb_vcp_timeout); if (arg < 0) goto cmd_bad; if (cin_wait(usb_vcp_timeout) != PROTO_EOC) goto cmd_bad; switch (arg) { case PROTO_DEVICE_BL_REV: VCP_send_str((uint8_t*)&bl_proto_rev); break; default: goto cmd_bad; } break; case PROTO_START_TRANS: if (cin_wait(usb_vcp_timeout) != PROTO_EOC) goto cmd_bad; address = 0; memset(tmpbuf,0,EERROM_SIZE); break; case PROTO_SET_PARAMS: arg = cin_wait(usb_vcp_timeout); if (arg < 0) goto cmd_bad; // sanity-check arguments if (arg % 4) goto cmd_bad; if ((address + arg) > EERROM_SIZE) goto cmd_bad; for (int i = 0; i < arg; i++) { c = cin_wait(usb_vcp_timeout); if (c < 0) goto cmd_bad; tmpbuf[address++] = c; } break; case PROTO_END_TRANS: if (cin_wait(usb_vcp_timeout) != PROTO_EOC) goto cmd_bad; //ensure we receive right size if(address == EERROM_SIZE) { memcpy(eeprom_buffer.c,tmpbuf,EERROM_SIZE); // bool ret = StoreParams(); // if(!ret) // { // //TODO - handle flash write error here // } } break; case PROTO_SAVE_TO_FLASH: if (cin_wait(usb_vcp_timeout) != PROTO_EOC) goto cmd_bad; //ensure we receive right size if(address == EERROM_SIZE) { bool ret = StoreParams(); if(!ret) { //TODO - handle flash write error here } } break; case PROTO_GET_PARAMS: if (cin_wait(usb_vcp_timeout) != PROTO_EOC) goto cmd_bad; for (int i = 0; i < EERROM_SIZE; i++) { VCP_put_char(eeprom_buffer.c[i]); //TM_USB_VCP_Putc(testbuf[i]); //vTaskDelay( 1 / portTICK_RATE_MS ); } break; case PROTO_BL_UPLOAD: if (cin_wait(usb_vcp_timeout) != PROTO_EOC) goto cmd_bad; sync_response(); vTaskDelay( 200 / portTICK_RATE_MS ); GPIO_SetBits(GPIOB,GPIO_Pin_12); vTaskDelay( 500 / portTICK_RATE_MS ); GPIO_ResetBits(GPIOB,GPIO_Pin_12); __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | SCB_AIRCR_SYSRESETREQ_Msk); /* Keep priority group unchanged */ __DSB(); /* Ensure completion of memory access */ while(1); break; default: continue; } // send the sync response for this command sync_response(); continue; } vTaskDelay( 10 / portTICK_RATE_MS ); continue; cmd_bad: // send an 'invalid' response but don't kill the timeout - could be garbage invalid_response(); continue; cmd_fail: // send a 'command failed' response but don't kill the timeout - could be garbage failure_response(); continue; } }