📄 send.c
字号:
/***********************************************************************//* *//* Module: send.c *//* Release: 2001.3 *//* Version: 99.0 *//* Purpose: send() and sendto() implementation *//* *//*---------------------------------------------------------------------*//* *//* Copyright 1999, Blunk Microsystems *//* ALL RIGHTS RESERVED *//* *//* Licensees have the non-exclusive right to use, modify, or extract *//* this computer program for software development at a single site. *//* This program may be resold or disseminated in executable format *//* only. The source code may not be redistributed or resold. *//* *//***********************************************************************/#include "../tcp_ipp.h"#include "../tcp/tcp.h"#include "../ip/ip.h"#include <string.h>/***********************************************************************//* Local Function Definitions *//***********************************************************************//***********************************************************************//* tcp_send: Transmit data over a TCP socket *//* *//* Inputs: sock = pointer to a TCP socket *//* ptr = pointer to source buffer *//* len = length of data *//* flags = behavior modifiers *//* *//* Returns: number written or -1 with errno set to error code *//* *//***********************************************************************/static int tcp_send(SOCKET sock, const ui8 *ptr, uint len, int flags){ int space, sboff; /*-------------------------------------------------------------------*/ /* Check for available space in send buffer. */ /*-------------------------------------------------------------------*/ space = sock->sb_size - sock->sb_count; TcpAssert(space >= 0); if (space == 0) { /*-----------------------------------------------------------------*/ /* Return error if operation is non-blocking. */ /*-----------------------------------------------------------------*/ if (((sock->flags & SF_NONBLKNG) && (flags & MSG_WAITALL) == 0) || (flags & MSG_DONTWAIT)) { NetError(sock, EWOULDBLOCK); return -1; } /*-----------------------------------------------------------------*/ /* Else wait til there is space in buffer. */ /*-----------------------------------------------------------------*/ else { /*---------------------------------------------------------------*/ /* Wait for "data acknowledged" event. */ /*---------------------------------------------------------------*/ NetPendEvent(sock, SE_DATA_ACKED, sock->send_timeo); /*---------------------------------------------------------------*/ /* Check if timed out or connection reset or aborted. */ /*---------------------------------------------------------------*/ if (sock->error) { NetError(sock, sock->error); return -1; } /*---------------------------------------------------------------*/ /* Redo space calculation. */ /*---------------------------------------------------------------*/ space = sock->sb_size - sock->sb_count; TcpAssert(space > 0); } } /*-------------------------------------------------------------------*/ /* Check if sending of urgent data is requested. */ /*-------------------------------------------------------------------*/ if (flags & MSG_OOB) { /*-----------------------------------------------------------------*/ /* Urgent mode is entered only if last byte of write is included. */ /*-----------------------------------------------------------------*/ if (space >= len) { sock->surg_seq = sock->snd_nxt + len - 1; sock->flags |= (SF_SUPOK | SF_SENDFLG); } } /*-------------------------------------------------------------------*/ /* Limit len to minimum of requested length and available space. */ /*-------------------------------------------------------------------*/ len = min(len, space); /*-------------------------------------------------------------------*/ /* Calculate starting offset of free space in send buffer. */ /*-------------------------------------------------------------------*/ sboff = (sock->sb_start + sock->sb_count) % sock->sb_size; /*-------------------------------------------------------------------*/ /* Copy data from user's buffer to socket's send buffer. */ /*-------------------------------------------------------------------*/ if ((sboff + len) <= sock->sb_size) { memcpy(&sock->sbuf[sboff], ptr, len); } else { int len1 = sock->sb_size - sboff; memcpy(&sock->sbuf[sboff], ptr, len1); memcpy(&sock->sbuf[0], ptr + len1, len - len1); } /*-------------------------------------------------------------------*/ /* Update socket send data count. */ /*-------------------------------------------------------------------*/ sock->sb_count += len; /*-------------------------------------------------------------------*/ /* Try sending data if output state is "idle" or "transmitting". */ /*-------------------------------------------------------------------*/ if (sock->out_state <= TCPO_XMIT) TcpTryOut(sock); return len;}/***********************************************************************//* Global Function Definitions *//***********************************************************************//***********************************************************************//* sendto: Write data to socket *//* *//* Inputs: s = socket identifier *//* src = pointer to source data *//* wanted = amount of data requested sent *//* flags = option flags *//* to = pointer to optional destination address *//* tolen = sizeof(struct sockaddr_in) *//* *//* Returns: -1 if errors, else number of characters written *//* *//***********************************************************************/int sendto(int s, const void *src, int wanted, int flags, void *to, int tolen){ SOCKET sock = &Socks[s - 1]; int len, sent = -1; struct sockaddr_in *addr = to; Route *route;#if OS_PARM_CHECK /*-------------------------------------------------------------------*/ /* Verify protocol has been initialized. */ /*-------------------------------------------------------------------*/ if (!Net.Initialized) { NetError(NULL, ENETDOWN); return -1; } /*-------------------------------------------------------------------*/ /* Check for valid socket ID. */ /*-------------------------------------------------------------------*/ if (InvalidHandle(s)) { NetError(NULL, ENOTSOCK); return -1; } /*-------------------------------------------------------------------*/ /* If used, check that source address is valid. */ /*-------------------------------------------------------------------*/ if (wanted && (src == NULL)) { NetError(sock, EFAULT); return -1; } /*-------------------------------------------------------------------*/ /* Check that requested data length is not negative. */ /*-------------------------------------------------------------------*/ if (wanted < 0) { NetError(sock, EINVAL); return -1; }#endif /*-------------------------------------------------------------------*/ /* Gain exclusive socket API access and stack internals access. */ /*-------------------------------------------------------------------*/ if (semPend(sock->api_access, WAIT_FOREVER)) { NetError(NULL, ENOTSOCK); return -1; } semPend(Net.IntSem, WAIT_FOREVER); /*-------------------------------------------------------------------*/ /* Check if socket has been shutdown for sends. */ /*-------------------------------------------------------------------*/ if (sock->flags & SF_SND_SHUT) { NetError(sock, ESHUTDOWN); goto send_exit; } /*-------------------------------------------------------------------*/ /* UDP socket write. */ /*-------------------------------------------------------------------*/ if (sock->type == SOCK_DGRAM) { NetBuf *buf;#if OS_PARM_CHECK /*-----------------------------------------------------------------*/ /* Check for illegal flag options. */ /*-----------------------------------------------------------------*/ if (flags & (MSG_DONTWAIT | MSG_OOB | MSG_WAITALL)) { NetError(sock, EOPNOTSUPP); goto send_exit; }#endif /*-----------------------------------------------------------------*/ /* If local port is not specified, pick one. */ /*-----------------------------------------------------------------*/ if (sock->local.sin_port == 0) { sock->local.sin_port = UdpNextPort(); if (sock->local.sin_port == 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -