BOOL ClientAuthenticate(const char *name, const char *hostname) { int rc, rcISC; SEC_WINNT_AUTH_IDENTITY nameAndPwd = {0}; int bytesReceived = 0, bytesSent = 0; char myTokenSource[256]; TimeStamp useBefore; DWORD ctxReq, ctxAttr; int dwRead,dwWritten; // input and output buffers SecBufferDesc obd, ibd; SecBuffer ob, ib[2]; BOOL haveInbuffer = FALSE; BOOL haveContext = FALSE; SCHANNEL_CRED cred = {0}; PCCERT_CONTEXT cert = NULL; HANDLE hMy = CertOpenSystemStore(0,"MY"); if(!hMy) { rcISC = SEC_E_NO_CREDENTIALS; server_error(1,"[%08x] %s\n",rcISC,GetErrorString(rcISC)); return FALSE; } if(name) { cert = CertFindCertificateInStore(hMy, X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR, (const wchar_t *)cvs::wide(name), NULL); if(!cert) { rcISC = SEC_E_NO_CREDENTIALS; server_error(1,"No certificate for '%s': %s\n",name,GetErrorString(rcISC)); return FALSE; } } cred.dwVersion = SCHANNEL_CRED_VERSION; cred.dwFlags = SCH_CRED_USE_DEFAULT_CREDS; if(cert) { cred.cCreds = 1; cred.paCred = &cert; } rc = AcquireCredentialsHandle( NULL, "SChannel", SECPKG_CRED_OUTBOUND, NULL, &cred, NULL, NULL, &credHandle, &useBefore ); ctxReq = ISC_REQ_MANUAL_CRED_VALIDATION | ISC_REQ_INTEGRITY | ISC_REQ_CONFIDENTIALITY | ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_STREAM | ISC_REQ_USE_SUPPLIED_CREDS; strncpy(myTokenSource,hostname,sizeof(myTokenSource)); CertCloseStore(hMy,0); ib[0].pvBuffer = NULL; while ( 1 ) { obd.ulVersion = SECBUFFER_VERSION; obd.cBuffers = 1; obd.pBuffers = &ob; // just one buffer ob.BufferType = SECBUFFER_TOKEN; // preping a token here ob.cbBuffer = secPackInfo->cbMaxToken; ob.pvBuffer = malloc(secPackInfo->cbMaxToken); rcISC = InitializeSecurityContext( &credHandle, haveContext? &contextHandle: NULL, myTokenSource, ctxReq, 0, SECURITY_NATIVE_DREP, haveInbuffer? &ibd: NULL, 0, &contextHandle, &obd, &ctxAttr, &useBefore ); if ( ib[0].pvBuffer != NULL ) { free(ib[0].pvBuffer); ib[0].pvBuffer = NULL; } if ( rcISC == SEC_I_COMPLETE_AND_CONTINUE || rcISC == SEC_I_COMPLETE_NEEDED ) { CompleteAuthToken( &contextHandle, &obd ); if ( rcISC == SEC_I_COMPLETE_NEEDED ) rcISC = SEC_E_OK; else if ( rcISC == SEC_I_COMPLETE_AND_CONTINUE ) rcISC = SEC_I_CONTINUE_NEEDED; } if(rcISC<0) { server_error(1,"[%08x] %s\n",rcISC,GetErrorString(rcISC)); } // send the output buffer off to the server if ( ob.cbBuffer != 0 ) { if((dwWritten=tcp_write( (const char *) ob.pvBuffer, ob.cbBuffer))<=0) break; bytesSent += dwWritten; } free(ob.pvBuffer); ob.pvBuffer = NULL; ob.cbBuffer = 0; if ( rcISC != SEC_I_CONTINUE_NEEDED ) break; // prepare to get the server's response ibd.ulVersion = SECBUFFER_VERSION; ibd.cBuffers = 2; ibd.pBuffers = ib; // just one buffer ib[0].BufferType = SECBUFFER_TOKEN; // preping a token here ib[0].cbBuffer = secPackInfo->cbMaxToken; ib[0].pvBuffer = malloc(secPackInfo->cbMaxToken); ib[1].cbBuffer = 0; ib[1].pvBuffer = NULL; ib[1].BufferType = SECBUFFER_EMPTY; // Spare stuff // receive the server's response if((dwRead=tcp_read(ib[0].pvBuffer,ib[0].cbBuffer))<=0) break; bytesReceived += dwRead; // by now we have an input buffer and a client context haveInbuffer = TRUE; haveContext = TRUE; } // we arrive here as soon as InitializeSecurityContext() // returns != SEC_I_CONTINUE_NEEDED. if ( rcISC != SEC_E_OK ) haveContext = FALSE; else haveContext = TRUE; /* Looopback kerberos needs this */ return haveContext; }
static int echo_worker(void *socket) { tcp_socket_t *s = socket; for (;;) { uint8_t buf[1024]; ssize_t ret = tcp_read(s, buf, sizeof(buf)); if (ret <= 0) break; tcp_write(s, buf, ret); if (ret <= 0) break; } TRACEF("echo worker exiting\n"); tcp_close(s); return 0; }
static void TCP_send(struct tcp_pcb *tpcb, TCP *es) { struct pbuf *ptr; err_t wr_err = ERR_OK; while ((wr_err == ERR_OK) && (es->tx != NULL) && (es->tx->len <= tcp_sndbuf(tpcb))) { ptr=es->tx; /* get pointer on pbuf from es structure & enqueue data for transmission */ wr_err=tcp_write(tpcb,ptr->payload,ptr->len, 1); if (wr_err == ERR_OK) { es->tx = ptr->next; if (es->tx != NULL) { pbuf_ref(es->tx); /* increment reference count for es->p */ } pbuf_free(ptr); /* free pbuf: will free pbufs up to es->p (because es->p has a reference count > 0) */ } else if(wr_err == ERR_MEM) { /* we are low on memory, try later / harder, defer to poll */ es->tx = ptr; } else { } /* other problem ?? */ } }
static int mg_lwip_tcp_write(struct tcp_pcb *tpcb, const void *data, uint16_t len) { len = MIN(tpcb->mss, MIN(len, tpcb->snd_buf)); if (len == 0) { DBG(("%p no buf avail %u %u %u %p %p", tpcb, tpcb->acked, tpcb->snd_buf, tpcb->snd_queuelen, tpcb->unsent, tpcb->unacked)); tcp_output(tpcb); return 0; } err_t err = tcp_write(tpcb, data, len, TCP_WRITE_FLAG_COPY); tcp_output(tpcb); DBG(("%p tcp_write %u = %d", tpcb, len, err)); if (err != ERR_OK) { /* * We ignore ERR_MEM because memory will be freed up when the data is sent * and we'll retry. */ return err == ERR_MEM ? 0 : -1; } return len; }
//***************************************************************************** // // Send a request to the server // // \param pcRequest request to be sent // \param ui32Size length of the request to be sent. this is usually the size // of the request minus the termination character // // This function will send the request to the connected server // // \return the lwIP error code. // //***************************************************************************** err_t EthClientSend(char *pcRequest, uint32_t ui32Size) { err_t eError; eError = tcp_write(g_sEnet.psTCP, pcRequest, ui32Size, TCP_WRITE_FLAG_COPY); // // Write data for sending (but does not send it immediately). // if(eError == ERR_OK) { // // Find out what we can send and send it // tcp_output(g_sEnet.psTCP); } return(eError); }
static err_t sent(void *arg, struct tcp_pcb *tpcb, u16_t len) { struct iperf_state *is = (struct iperf_state *) arg; is->sent_bytes += len; if (is->amount > 0 && is->sent_bytes > is->amount) { finish_send(is, tpcb); return ERR_OK; } else if (is->amount < 0 && (rte_get_timer_cycles()-is->send_start_ticks) > -is->amount) { finish_send(is, tpcb); return ERR_OK; } int space; while ((space = tcp_sndbuf(tpcb)) >= sizeof(send_data)) { tcp_write(tpcb, send_data, sizeof(send_data), 0); } return ERR_OK; }
/* * \brief This method should be called when a trace should be dumped on the network. */ static void bfscope_trace_dump_network(void) { assert(bfscope_client != NULL); assert(trace_length > 0); printf("bfscope: sending %lu bytes to network...\n", trace_length); /* Send length field */ char tmpbuf[10]; int len; len = snprintf(tmpbuf, 9, "%08ld", trace_length); tcp_write(bfscope_client, tmpbuf, 8, TCP_WRITE_FLAG_COPY); /* Start to send the trace */ timestamp_start = rdtsc(); trace_sent = 0; bfscope_trace_send(bfscope_client); tcp_output(bfscope_client); }
/** * read - the function will write bytes to the file * * @param fd the file handle * @param buf the sending buffer point * @param count the maximum bytes to be sent * * @return the result */ ssize_t _write(int fd, const void *buf, size_t count) { struct socket *socket = (struct socket *)fd; ssize_t size = -1; if (SOCK_STREAM == socket->type) { size = tcp_write(socket->pcb, buf, count, TCP_WRITE_FLAG_COPY); } else if (SOCK_PACKET == socket->type) { struct pbuf *pbuf = pbuf_alloc(PBUF_RAW, count, PBUF_POOL); if ((pbuf = ippkg_pack((os_u8 *)buf, count)) == NULL) return -1; size = udp_send(socket->pcb, pbuf); } return size; }
int do_http_post(struct tcp_pcb* pcb, char* req, int rlen) { int BUFSIZE = 1024; unsigned char buf[BUFSIZE]; int len, n; char* p; if (is_cmd_led(req)) { n = toggle_leds(); len = generate_http_header((char*)buf, "js", 1); p = (char*)buf + len; *p++ = n ? '1':'0'; *p = 0; len++; xil_printf("http POST: ledstatus: %x\r\n", n); } else if (is_cmd_switch(req)) { unsigned s = get_switch_state(); int n_switches = 4; xil_printf("http POST: switch state: %x\r\n", s); len = generate_http_header((char*)buf, "js", n_switches); p = (char*)buf + len; for (n=0; n<n_switches; n++, p++) { *p = '0' + (s & 0x1); s >>= 1; } *p = 0; len += n_switches; } if (tcp_write(pcb, buf, len, 1) != ERR_OK) { xil_printf("error writing http POST response to socket\r\n"); xil_printf("http header = %s\r\n", buf); return -1; } return 0; }
/** * Function: recvRemotePacket * Description: 当客户端收到服务器发送的数据时调用的回调函数 * @param arg 回调时传递回来的参数 * @param tpcb 当前连接的PCB * @param p 存放服务器发送过来的数据 * @param err 回调时传递回来的错误码 * @return err_t 类型的状态码 **/ err_t recvRemotePacket(void *arg, struct tcp_pcb *tpcb,struct pbuf *p, err_t err) { struct pbuf *temp; char *data; err_t error_status; int loc = 0; if ((err != ERR_OK) || (p == NULL)) { if(p != NULL) { tcp_recved(tpcb, p->tot_len); pbuf_free(p); } return ERR_OK; } if(p == NULL) { printf("recv data is empty\n\r"); } else { data = (char*)malloc(p->tot_len); memset(data,0,p->tot_len); memset(data,0,p->tot_len); for(temp = p; temp ; temp = temp->next) { memcpy(&data[loc],temp->payload,temp->len); loc += temp->len; } } tcp_recved(tpcb, p->tot_len); if(p != NULL) { pbuf_free(p); } error_status = tcp_write(tpcb,data,p->len,1); if(error_status != ERR_OK) { //发送数据失败 printf("data send failed\n\r"); return ERR_MEM; } tcp_output(tpcb); free(data); data = NULL; }
static int chargen_worker(void *socket) { uint64_t count = 0; tcp_socket_t *s = socket; /* enough buffer to hold an entire defacto chargen sequences */ #define CHARGEN_BUFSIZE (0x5f * 0x5f) // 9025 bytes uint8_t *buf = malloc(CHARGEN_BUFSIZE); if (!buf) return -1; /* generate the sequence */ uint8_t c = '!'; for (size_t i = 0; i < CHARGEN_BUFSIZE; i++) { buf[i] = c++; if (c == 0x7f) c = ' '; } lk_time_t t = current_time(); for (;;) { ssize_t ret = tcp_write(s, buf, CHARGEN_BUFSIZE); //TRACEF("tcp_write returns %d\n", ret); if (ret < 0) break; count += ret; } t = current_time() - t; TRACEF("chargen worker exiting, wrote %llu bytes in %u msecs (%llu bytes/sec)\n", count, (uint32_t)t, count * 1000 / t); free(buf); tcp_close(s); return 0; }
/* * \brief Send the next chunk of trace data down given TCP connection */ static void bfscope_trace_send(struct tcp_pcb *tpcb) { char *bufptr; int len; //DEBUG("tcp_sndbuf=%d\n", tcp_sndbuf(tpcb)); bufptr = trace_buf + trace_sent; len = trace_length - trace_sent; int more = 0; if (len > tcp_sndbuf(tpcb)) { len = tcp_sndbuf(tpcb); more = 1; } /* Give the data to LWIP until it runs out of buffer space */ err_t lwip_err = tcp_write(tpcb, bufptr, len, TCP_WRITE_FLAG_COPY | (more ? TCP_WRITE_FLAG_MORE : 0)); //DEBUG("%d %ld+%d\n", r, trace_sent, len); if (lwip_err == ERR_MEM) { printf("bfscope: lwip: out of memory\n"); return; } trace_sent += len; if (trace_sent >= trace_length) { /* No more events */ uint64_t timestamp_stop = rdtsc(); DEBUG("bfscope: done (%lu bytes) in %ld cycles\n", trace_sent, timestamp_stop - timestamp_start); bfscope_trace_dump_finished(); } }
int echo_client_send (void) { err_t err; struct tcp_pcb *pcb = echo_client_pcb; int buflen; if (!echo_client_pcb) { printd ("No connection.\n"); return -1; } else { printd ("Connection found.\n"); } buflen = tcp_sndbuf (pcb); if (buflen >= strlen (send_buf)) { printd ("Space available: %d\n", buflen); err = tcp_write (pcb, send_buf, strlen (send_buf), TCP_WRITE_FLAG_COPY); if (err == ERR_OK) { printd ("Enqueue succeeded.\n"); err = tcp_output (pcb); if (err == ERR_OK) { printd ("Send succeeded.\n"); } else { printd ("Send failed.\n"); return -2; } } else { printd ("Enqueue failed.\n"); return -3; } } else { printd ("Space unavailable: %d\n", buflen); return -4; } return 0; }
static int ps_send_deferred_acks(struct tcp_pcb *pcb) { int num = (ps_deferred_ack_produce + PS_DEFERRED_ACK_MAX - ps_deferred_ack_consume) % PS_DEFERRED_ACK_MAX; if (num) { outputf("%d deferred acks\n", num); } int count = 0; int consume = ps_deferred_ack_consume; err_t err = 0; while (consume != ps_deferred_ack_produce) { struct dac_response response; response.response = ps_deferred_ack_queue[consume].resp; response.command = ps_deferred_ack_queue[consume].cmd; fill_status(&response.dac_status); err = tcp_write(pcb, &response, sizeof(response), TCP_WRITE_FLAG_COPY); if (err < 0) break; count++; consume = (consume + 1) % PS_DEFERRED_ACK_MAX; } ps_deferred_ack_consume = consume; if (err == ERR_MEM) err = 0; if (num) outputf("sent %d deferred acks, err %d", count, err); return err; }
//服务器连接成功后将要调用的函数 err_t tcp_server_accept(void *arg, struct tcp_pcb *newpcb, err_t err){ err_t ret_err; struct tcp_server_state* ts; ts = mem_malloc(sizeof(struct tcp_server_state)); //申请内存 if(ts!=NULL){ ts->state = ES_RECEIVED; //可以接收数据了 lwip_flag |= LWIP_CONNECTED; //已经连接上了 tcp_write(newpcb,respond,strlen(respond),1); //回应信息 tcp_arg(newpcb, ts); //将程序的协议控制块的状态传递给多有的回调函数 tcp_recv(newpcb, tcp_server_recv); //指定连接接收到新的数据之后将要调用的回调函数 tcp_err(newpcb, tcp_server_error); //指定连接出错将要调用的函数 tcp_poll(newpcb, tcp_server_poll, 0); //指定轮询时将要调用的回调函数 ret_err = ERR_OK; }else{ ret_err = ERR_MEM; } return ret_err; }
// Sends the next chunk of data. static void send_data(struct tcp_pcb *pcb, struct http_state *hs) { err_t err; u16_t len; CYG_TEST_INFO("Sending data"); // We cannot send more data than space available in the send buffer len = tcp_sndbuf(pcb) < hs->left ? tcp_sndbuf(pcb) : hs->left; do { err = tcp_write(pcb, hs->file, len, 0); if (err == ERR_MEM) { len /= 2; } } while (err == ERR_MEM && len > 1); if (err == ERR_OK) { hs->file += len; hs->left -= len; } }
/** * @brief reply to the all user who is aliving. * @param *pcb: the poiter of the pcb struct. *Cmd: the pointer of the 24byte date. * @retval None */ static void Pcb_Write_ALL(const void *data) { int try_times = 0; int t = 0; for(t = 0; t < 11; t++) { if(pad_info[t].user == TRUE && pad_info[t].pad_living>0) { if(pad_info[t].socket != sever_pcb) { while(tcp_write(pad_info[t].socket, data, 24, 1)!= ERR_OK && try_times < 500) { try_times++; vTaskDelay(1); } } } } Pcb_Write_Sever(data); }
size_t EthernetClient::write(const uint8_t *buf, size_t size) { uint32_t i = 0, inc = 0; boolean stuffed_buffer = false; struct tcp_pcb * cpcb = (tcp_pcb*)cs->cpcb; /* cs->cpcb may change to NULL during interrupt servicing */ if (!cpcb) return 0; // Attempt to write in 1024-byte increments. while (i < size) { inc = (size - i) < 1024 ? size - i : 1024; err_t err = tcp_write(cpcb, buf + i, inc, TCP_WRITE_FLAG_COPY); if (err != ERR_MEM) { // Keep enqueueing the lwIP buffer until it's full... i += inc; stuffed_buffer = false; } else { if (!stuffed_buffer) { // Buffer full; force output if (cs->mode) tcp_output(cpcb); stuffed_buffer = true; } else { delay(1); // else wait a little bit for lwIP to flush its buffers } } } // flush any remaining queue contents if (!stuffed_buffer) { if (cs->mode) tcp_output(cpcb); } return size; }
/** * This function is called when data has been acknowledged by the * remote endpoint. */ static err_t on_tcp_sent(void *arg_p, struct tcp_pcb *pcb_p, u16_t len) { struct socket_t *socket_p = arg_p; struct send_to_args_t *args_p; size_t size; if (socket_p->output.cb.state == STATE_SENDTO) { args_p = socket_p->output.cb.args_p; size = MIN(args_p->extra.left, tcp_sndbuf(((struct tcp_pcb *)socket_p->pcb_p))); if (tcp_write(socket_p->pcb_p, args_p->buf_p, size, TCP_WRITE_FLAG_COPY) == ERR_OK) { args_p->buf_p += size; args_p->extra.left -= size; /* Resume if all data has been written. */ if (args_p->extra.left == 0) { tcp_output(socket_p->pcb_p); socket_p->output.cb.state = STATE_IDLE; fs_counter_increment(&module.tcp_tx_bytes, args_p->size); resume_thrd(socket_p->output.cb.thrd_p, args_p->size); } else { socket_p->output.cb.state = STATE_SENDTO; } } else { resume_thrd(socket_p->output.cb.thrd_p, 0); } } return (ERR_OK); }
int /*if < 0 : NetTcpSocketErr*/ LwipNetTcpSocket::send(const char* buf, int len) { if( !m_pPcb ) //Pcb doesn't exist (anymore) return NETTCPSOCKET_MEM; int outLen = MIN( len, tcp_sndbuf( (tcp_pcb*) m_pPcb) ); //tcp_sndbuf() returns the number of bytes available in the output queue, so never go above it err_t err = tcp_write( (tcp_pcb*) m_pPcb, (void*) buf, outLen, TCP_WRITE_FLAG_COPY ); //Flags are TCP_WRITE_FLAG_COPY & TCP_WRITE_FLAG_MORE (see tcp_out.c) : //If TCP_WRITE_FLAG_MORE is not set ask client to push buffered data to app if(err) { switch( err ) { case ERR_CONN: return (int) NETTCPSOCKET_SETUP; //Not connected properly case ERR_ARG: return (int) NETTCPSOCKET_SETUP; //Wrong args ! (like buf pointing to NULL) case ERR_MEM: default: return (int) NETTCPSOCKET_MEM; //Not enough memory } } return outLen; }
static err_t echo_recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { /* do not read the packet if we are not in ESTABLISHED state */ if (!p) { tcp_close(tpcb); tcp_recv(tpcb, NULL); return ERR_OK; } /* indicate that the packet has been received */ tcp_recved(tpcb, p->len); /* echo back the payload */ /* in this case, we assume that the payload is < TCP_SND_BUF */ if (tcp_sndbuf(tpcb) > p->len) { err = tcp_write(tpcb, p->payload, p->len, 1); } /* free the received pbuf */ pbuf_free(p); return ERR_OK; }
static void proc_rx_data(struct tcp_pcb * pcb, struct telnetio_dev *teldev, struct pbuf *p) { struct pbuf *q; unsigned char *c; int num, i; TELNETD_DEBUG(("line:%d, %s()\n", __LINE__, __FUNCTION__)); rt_sem_take(teldev->rx_rb_buf.rw_sem, RT_WAITING_FOREVER); for(q=p; NULL!=q; q=q->next) { c = q->payload; for(i=0; i<q->len; i++, c++) proc_rx_byte(pcb, teldev, *c); } rt_sem_release(teldev->rx_rb_buf.rw_sem); num = teldev->iac_index; if (0 != num) { tcp_write(pcb, teldev->iac_buf, num, TCP_WRITE_FLAG_COPY); teldev->iac_index = 0; } return; }
size_t device_write(const __ptr_t buf, size_t n, struct gn_statemachine *state) { switch (state->device.type) { case GN_CT_DKU2: case GN_CT_Serial: case GN_CT_Infrared: return serial_write(state->device.fd, buf, n, state); case GN_CT_Irda: return irda_write(state->device.fd, buf, n, state); case GN_CT_Bluetooth: return bluetooth_write(state->device.fd, buf, n, state); case GN_CT_Tekram: return tekram_write(state->device.fd, buf, n, state); case GN_CT_TCP: return tcp_write(state->device.fd, buf, n, state); case GN_CT_DKU2LIBUSB: return fbusdku2usb_write(buf, n, state); case GN_CT_SOCKETPHONET: return socketphonet_write(state->device.fd, buf, n, state); default: break; } return 0; }
int TcpConnection::write(const char* data, int len, uint8_t apiflags /* = TCP_WRITE_FLAG_COPY*/) { //int original = len; u16_t available = getAvailableWriteSize(); if (available < len) { if (available == 0) return -1; // No memory else len = available; } err_t err = tcp_write(tcp, data, len, apiflags); if (err == ERR_OK) { debugf("TCP connection send: %d ", len); return len; } else { debugf("TCP connection failed with err %d ", err); return -1; } }
/** * See if more data needs to be written from a previous call to netconn_write. * Called initially from do_write. If the first call can't send all data * (because of low memory or empty send-buffer), this function is called again * from sent_tcp() or poll_tcp() to send more data. If all data is sent, the * blocking application thread (waiting in netconn_write) is released. * * @param conn netconn (that is currently in state NETCONN_WRITE) to process * @return ERR_OK * ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished */ static err_t do_writemore(struct netconn *conn) { err_t err; void *dataptr; u16_t len, available; u8_t write_finished = 0; size_t diff; u8_t dontblock = netconn_is_nonblocking(conn) || (conn->current_msg->msg.w.apiflags & NETCONN_DONTBLOCK); u8_t apiflags = conn->current_msg->msg.w.apiflags; LWIP_ASSERT("conn != NULL", conn != NULL); LWIP_ASSERT("conn->state == NETCONN_WRITE", (conn->state == NETCONN_WRITE)); LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); LWIP_ASSERT("conn->pcb.tcp != NULL", conn->pcb.tcp != NULL); LWIP_ASSERT("conn->write_offset < conn->current_msg->msg.w.len", conn->write_offset < conn->current_msg->msg.w.len); #if LWIP_SO_SNDTIMEO if ((conn->send_timeout != 0) && ((s32_t)(sys_now() - conn->current_msg->msg.w.time_started) >= conn->send_timeout)) { write_finished = 1; if (conn->write_offset == 0) { /* nothing has been written */ err = ERR_WOULDBLOCK; conn->current_msg->msg.w.len = 0; } else { /* partial write */ err = ERR_OK; conn->current_msg->msg.w.len = conn->write_offset; } } else #endif /* LWIP_SO_SNDTIMEO */ { dataptr = (u8_t*)conn->current_msg->msg.w.dataptr + conn->write_offset; diff = conn->current_msg->msg.w.len - conn->write_offset; if (diff > 0xffffUL) { /* max_u16_t */ len = 0xffff; #if LWIP_TCPIP_CORE_LOCKING conn->flags |= NETCONN_FLAG_WRITE_DELAYED; #endif apiflags |= TCP_WRITE_FLAG_MORE; } else { len = (u16_t)diff; } available = tcp_sndbuf(conn->pcb.tcp); if (available < len) { /* don't try to write more than sendbuf */ len = available; if (dontblock) { if (!len) { err = ERR_WOULDBLOCK; goto err_mem; } } else { #if LWIP_TCPIP_CORE_LOCKING conn->flags |= NETCONN_FLAG_WRITE_DELAYED; #endif apiflags |= TCP_WRITE_FLAG_MORE; } } LWIP_ASSERT("do_writemore: invalid length!", ((conn->write_offset + len) <= conn->current_msg->msg.w.len)); err = tcp_write(conn->pcb.tcp, dataptr, len, apiflags); /* if OK or memory error, check available space */ if ((err == ERR_OK) || (err == ERR_MEM)) { err_mem: if (dontblock && (len < conn->current_msg->msg.w.len)) { /* non-blocking write did not write everything: mark the pcb non-writable and let poll_tcp check writable space to mark the pcb writable again */ API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); conn->flags |= NETCONN_FLAG_CHECK_WRITESPACE; } else if ((tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT) || (tcp_sndqueuelen(conn->pcb.tcp) >= TCP_SNDQUEUELOWAT)) { /* The queued byte- or pbuf-count exceeds the configured low-water limit, let select mark this pcb as non-writable. */ API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); } } if (err == ERR_OK) { conn->write_offset += len; if ((conn->write_offset == conn->current_msg->msg.w.len) || dontblock) { /* return sent length */ conn->current_msg->msg.w.len = conn->write_offset; /* everything was written */ write_finished = 1; conn->write_offset = 0; } tcp_output(conn->pcb.tcp); } else if ((err == ERR_MEM) && !dontblock) { /* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called we do NOT return to the application thread, since ERR_MEM is only a temporary error! */ /* tcp_write returned ERR_MEM, try tcp_output anyway */ tcp_output(conn->pcb.tcp); #if LWIP_TCPIP_CORE_LOCKING conn->flags |= NETCONN_FLAG_WRITE_DELAYED; #endif } else { /* On errors != ERR_MEM, we don't try writing any more but return the error to the application thread. */ write_finished = 1; conn->current_msg->msg.w.len = 0; } } if (write_finished) { /* everything was written: set back connection state and back to application task */ conn->current_msg->err = err; conn->current_msg = NULL; conn->state = NETCONN_NONE; #if LWIP_TCPIP_CORE_LOCKING if ((conn->flags & NETCONN_FLAG_WRITE_DELAYED) != 0) #endif { sys_sem_signal(&conn->op_completed); } } #if LWIP_TCPIP_CORE_LOCKING else return ERR_MEM; #endif return ERR_OK; }
void zmq::stream_engine_t::out_event () { zmq_assert (!io_error); // If write buffer is empty, try to read new data from the encoder. if (!outsize) { // Even when we stop polling as soon as there is no // data to send, the poller may invoke out_event one // more time due to 'speculative write' optimisation. if (unlikely (encoder == NULL)) { zmq_assert (handshaking); return; } outpos = NULL; outsize = encoder->encode (&outpos, 0); while (outsize < out_batch_size) { if ((this->*next_msg) (&tx_msg) == -1) break; encoder->load_msg (&tx_msg); unsigned char *bufptr = outpos + outsize; size_t n = encoder->encode (&bufptr, out_batch_size - outsize); zmq_assert (n > 0); if (outpos == NULL) outpos = bufptr; outsize += n; } // If there is no data to send, stop polling for output. if (outsize == 0) { output_stopped = true; reset_pollout (handle); return; } } // If there are any data to write in write buffer, write as much as // possible to the socket. Note that amount of data to write can be // arbitrarily large. However, we assume that underlying TCP layer has // limited transmission buffer and thus the actual number of bytes // written should be reasonably modest. const int nbytes = tcp_write (s, outpos, outsize); // IO error has occurred. We stop waiting for output events. // The engine is not terminated until we detect input error; // this is necessary to prevent losing incoming messages. if (nbytes == -1) { reset_pollout (handle); return; } outpos += nbytes; outsize -= nbytes; // If we are still handshaking and there are no data // to send, stop polling for output. if (unlikely (handshaking)) if (outsize == 0) reset_pollout (handle); }
int transfer_data() { uint16_t data[1900]; tcp_write(pcb, data, sizeof(data)/ sizeof(*data),0); // send some data return 0; }
// lwip calls this function when the connection is established static err_t hc_connected(void *arg, struct tcp_pcb *pcb, err_t err) { struct hc_state *hcstate = arg; char * headers; // error? if(err != ERR_OK) { hc_clearpcb(pcb); // Call return function (*hcstate->ReturnPage)(hcstate->Num, GEN_ERROR, NULL, 0); // Free wc hcstate free(hcstate->RecvData); free(hcstate); return(ERR_OK); } // Define Headers if(hcstate->PostVars == NULL) { // GET headers (without page)(+ \0) = 19 headers = malloc(19 + strlen(hcstate->Page)); sprintf(headers,"GET /%s HTTP/1.0\r\n\r\n", hcstate->Page); } else { // POST headers (without PostVars or Page)(+ \0) = 91 // Content-length: %d <== ??? (max 10) headers = malloc(91 + strlen(hcstate->PostVars) + strlen(hcstate->Page) + 10); sprintf(headers, "POST /%s HTTP/1.0\r\nContent-type: application/x-www-form-urlencoded\r\nContent-length: %d\r\n\r\n%s\r\n\r\n", hcstate->Page, strlen(hcstate->PostVars), hcstate->PostVars); } // Check if we are nut running out of memory if(headers == NULL) { hc_clearpcb(pcb); // Call return function (*hcstate->ReturnPage)(hcstate->Num, OUT_MEM, NULL, 0); // Free wc hcstate free(hcstate->RecvData); free(hcstate); return(ERR_OK); } // Send data tcp_write(pcb, headers, strlen(headers), 1); tcp_output(pcb); // remove headers free(headers); free(hcstate->PostVars); // postvars are send, so we don't need them anymore free(hcstate->Page); // page is requested, so we don't need it anymore return(ERR_OK); }
/** * See if more data needs to be written from a previous call to netconn_write. * Called initially from do_write. If the first call can't send all data * (because of low memory or empty send-buffer), this function is called again * from sent_tcp() or poll_tcp() to send more data. If all data is sent, the * blocking application thread (waiting in netconn_write) is released. * * @param conn netconn (that is currently in state NETCONN_WRITE) to process * @return ERR_OK * ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished */ static err_t do_writemore(struct netconn *conn) { err_t err; void *dataptr; u16_t len, available; u8_t write_finished = 0; size_t diff; LWIP_ASSERT("conn->state == NETCONN_WRITE", (conn->state == NETCONN_WRITE)); dataptr = (u8_t*)conn->write_msg->msg.w.dataptr + conn->write_offset; diff = conn->write_msg->msg.w.len - conn->write_offset; if (diff > 0xffffUL) { /* max_u16_t */ len = 0xffff; #if LWIP_TCPIP_CORE_LOCKING conn->write_delayed = 1; #endif } else { len = (u16_t)diff; } available = tcp_sndbuf(conn->pcb.tcp); if (available < len) { /* don't try to write more than sendbuf */ len = available; #if LWIP_TCPIP_CORE_LOCKING conn->write_delayed = 1; #endif } err = tcp_write(conn->pcb.tcp, dataptr, len, conn->write_msg->msg.w.apiflags); LWIP_ASSERT("do_writemore: invalid length!", ((conn->write_offset + len) <= conn->write_msg->msg.w.len)); if (err == ERR_OK) { conn->write_offset += len; if (conn->write_offset == conn->write_msg->msg.w.len) { /* everything was written */ write_finished = 1; conn->write_msg = NULL; conn->write_offset = 0; /* API_EVENT might call tcp_tmr, so reset conn->state now */ conn->state = NETCONN_NONE; } err = tcp_output_nagle(conn->pcb.tcp); conn->err = err; if ((err == ERR_OK) && (tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT)) { API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); } } else if (err == ERR_MEM) { /* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called we do NOT return to the application thread, since ERR_MEM is only a temporary error! */ /* tcp_enqueue returned ERR_MEM, try tcp_output anyway */ err = tcp_output(conn->pcb.tcp); //[MS_CHANGE] - return failure on output conn->err = ERR_MEM; write_finished = 1; #if LWIP_TCPIP_CORE_LOCKING conn->write_delayed = 1; #endif } else { /* On errors != ERR_MEM, we don't try writing any more but return the error to the application thread. */ conn->err = err; write_finished = 1; } if (write_finished) { /* everything was written: set back connection state and back to application task */ conn->state = NETCONN_NONE; #if LWIP_TCPIP_CORE_LOCKING if (conn->write_delayed != 0) #endif { sys_sem_signal(conn->op_completed); } } #if LWIP_TCPIP_CORE_LOCKING else return ERR_MEM; #endif return ERR_OK; }
int net_send(spdid_t spdid, net_connection_t nc, void *data, int sz) { struct intern_connection *ic; u16_t tid = cos_get_thd_id(); int ret = sz; // if (!cos_argreg_buff_intern(data, sz)) return -EFAULT; if (!net_conn_valid(nc)) return -EINVAL; if (sz > MAX_SEND) return -EMSGSIZE; // NET_LOCK_TAKE(); ic = net_conn_get_internal(nc); if (NULL == ic) { ret = -EINVAL; goto err; } if (tid != ic->tid) { ret = -EPERM; goto err; } switch (ic->conn_type) { case UDP: { struct udp_pcb *up; struct pbuf *p; /* There's no blocking in the UDP case, so this is simple */ up = ic->conn.up; p = pbuf_alloc(PBUF_TRANSPORT, sz, PBUF_ROM); if (NULL == p) { ret = -ENOMEM; goto err; } p->payload = data; if (ERR_OK != udp_send(up, p)) { pbuf_free(p); /* IP/port must not be set */ ret = -ENOTCONN; goto err; } pbuf_free(p); break; } case TCP: { struct tcp_pcb *tp; #define TCP_SEND_COPY #ifdef TCP_SEND_COPY void *d; struct packet_queue *pq; #endif tp = ic->conn.tp; if (tcp_sndbuf(tp) < sz) { ret = 0; break; } #ifdef TCP_SEND_COPY pq = malloc(sizeof(struct packet_queue) + sz); if (unlikely(NULL == pq)) { ret = -ENOMEM; goto err; } #ifdef TEST_TIMING pq->ts_start = timing_record(APP_PROC, ic->ts_start); #endif pq->headers = NULL; d = net_packet_data(pq); memcpy(d, data, sz); if (ERR_OK != (ret = tcp_write(tp, d, sz, 0))) { #else if (ERR_OK != (ret = tcp_write(tp, data, sz, TCP_WRITE_FLAG_COPY))) { #endif free(pq); printc("tcp_write returned %d (sz %d, tcp_sndbuf %d, ERR_MEM: %d)", ret, sz, tcp_sndbuf(tp), ERR_MEM); BUG(); } /* No implementation of nagle's algorithm yet. Send * out the packet immediately if possible. */ if (ERR_OK != (ret = tcp_output(tp))) { printc("tcp_output returned %d, ERR_MEM: %d", ret, ERR_MEM); BUG(); } ret = sz; break; } case TCP_CLOSED: ret = -EPIPE; break; default: BUG(); } err: // NET_LOCK_RELEASE(); return ret; } /************************ LWIP integration: **************************/ struct ip_addr ip, mask, gw; struct netif cos_if; static void cos_net_interrupt(char *packet, int sz) { void *d; int len; struct pbuf *p; struct ip_hdr *ih; struct packet_queue *pq; #ifdef TEST_TIMING unsigned long long ts; #endif // printc(">>> %d\n", net_lock.lock_id); NET_LOCK_TAKE(); // printc("<<< %d\n", net_lock.lock_id); assert(packet); ih = (struct ip_hdr*)packet; if (unlikely(4 != IPH_V(ih))) goto done; len = ntohs(IPH_LEN(ih)); if (unlikely(len != sz || len > MTU)) { printc("len %d != %d or > %d", len, sz, MTU); goto done; } p = pbuf_alloc(PBUF_IP, len, PBUF_ROM); if (unlikely(!p)) { prints("OOM in interrupt: allocation of pbuf failed.\n"); goto done; } /* For now, we're going to do an additional copy. Currently, * packets should be small, so this shouldn't hurt that badly. * This is done because 1) we are freeing the packet * elsewhere, 2) we want to malloc some (small) packets to * save space and free up the ring buffers, 3) it is difficult * to know in (1) which deallocation method (free or return to * ring buff) to use */ pq = malloc(len + sizeof(struct packet_queue)); if (unlikely(NULL == pq)) { printc("OOM in interrupt: allocation of packet data (%d bytes) failed.\n", len); pbuf_free(p); goto done; } pq->headers = d = net_packet_data(pq); #ifdef TEST_TIMING #ifdef TCP_SEND_COPY ts = pq->ts_start = timing_timestamp(); #endif #endif memcpy(d, packet, len); p->payload = p->alloc_track = d; /* hand off packet ownership here... */ if (ERR_OK != cos_if.input(p, &cos_if)) { prints("net: failure in IP input."); pbuf_free(p); goto done; } #ifdef TEST_TIMING timing_record(UPCALL_PROC, ts); #endif done: NET_LOCK_RELEASE(); return; }