⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rpc_transport.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
        /* need a non-blocking socket, otherwise accept() has a potential         * race-condition (poll() says it is readable, connection drops,         * and accept() blocks until the next connection comes...)         */        blocking = 1;        ret = ioctlsocket(sock, FIONBIO, &blocking);        if (ret < 0)        {            WARN("couldn't make socket non-blocking, error %d\n", ret);            RPCRT4_DestroyConnection(&tcpc->common);            status = RPC_S_OUT_OF_RESOURCES;            continue;        }        tcpc->common.Next = first_connection;        first_connection = &tcpc->common;    }    freeaddrinfo(ai);    /* if at least one connection was created for an endpoint then     * return success */    if (first_connection)    {        RpcConnection *conn;        /* find last element in list */        for (conn = first_connection; conn->Next; conn = conn->Next)            ;        EnterCriticalSection(&protseq->cs);        conn->Next = protseq->conn;        protseq->conn = first_connection;        LeaveCriticalSection(&protseq->cs);                TRACE("listening on %s\n", endpoint);        return RPC_S_OK;    }    ERR("couldn't listen on port %s\n", endpoint);    return status;}static RPC_STATUS rpcrt4_conn_tcp_handoff(RpcConnection *old_conn, RpcConnection *new_conn){  int ret;  struct sockaddr_in address;  socklen_t addrsize;  u_long blocking;  RpcConnection_tcp *server = (RpcConnection_tcp*) old_conn;  RpcConnection_tcp *client = (RpcConnection_tcp*) new_conn;  addrsize = sizeof(address);  ret = accept(server->sock, (struct sockaddr*) &address, &addrsize);  if (ret < 0)  {    ERR("Failed to accept a TCP connection: error %d\n", ret);    return RPC_S_OUT_OF_RESOURCES;  }  /* reset to blocking behaviour */  blocking = 0;  ret = ioctlsocket(ret, FIONBIO, &blocking);  client->sock = ret;  TRACE("Accepted a new TCP connection\n");  return RPC_S_OK;}static int rpcrt4_conn_tcp_read(RpcConnection *Connection,                                void *buffer, unsigned int count){  RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;  int r = recv(tcpc->sock, buffer, count, MSG_WAITALL);  TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, r);  return r;}static int rpcrt4_conn_tcp_write(RpcConnection *Connection,                                 const void *buffer, unsigned int count){  RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;  int r = write(tcpc->sock, buffer, count);  TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, r);  return r;}static int rpcrt4_conn_tcp_close(RpcConnection *Connection){  RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;  TRACE("%d\n", tcpc->sock);  if (tcpc->sock != -1)    close(tcpc->sock);  tcpc->sock = -1;  return 0;}static size_t rpcrt4_ncacn_ip_tcp_get_top_of_tower(unsigned char *tower_data,                                                   const char *networkaddr,                                                   const char *endpoint){    twr_tcp_floor_t *tcp_floor;    twr_ipv4_floor_t *ipv4_floor;    struct addrinfo *ai;    struct addrinfo hints;    int ret;    size_t size = sizeof(*tcp_floor) + sizeof(*ipv4_floor);    TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);    if (!tower_data)        return size;    tcp_floor = (twr_tcp_floor_t *)tower_data;    tower_data += sizeof(*tcp_floor);    ipv4_floor = (twr_ipv4_floor_t *)tower_data;    tcp_floor->count_lhs = sizeof(tcp_floor->protid);    tcp_floor->protid = EPM_PROTOCOL_TCP;    tcp_floor->count_rhs = sizeof(tcp_floor->port);    ipv4_floor->count_lhs = sizeof(ipv4_floor->protid);    ipv4_floor->protid = EPM_PROTOCOL_IP;    ipv4_floor->count_rhs = sizeof(ipv4_floor->ipv4addr);    hints.ai_flags          = AI_NUMERICHOST;    /* FIXME: only support IPv4 at the moment. how is IPv6 represented by the EPM? */    hints.ai_family         = PF_INET;    hints.ai_socktype       = SOCK_STREAM;    hints.ai_protocol       = IPPROTO_TCP;    hints.ai_addrlen        = 0;    hints.ai_addr           = NULL;    hints.ai_canonname      = NULL;    hints.ai_next           = NULL;    ret = getaddrinfo(networkaddr, endpoint, &hints, &ai);    if (ret)    {        ret = getaddrinfo("0.0.0.0", endpoint, &hints, &ai);        if (ret)        {            ERR("getaddrinfo failed: %s\n", gai_strerror(ret));            return 0;        }    }    if (ai->ai_family == PF_INET)    {        const struct sockaddr_in *sin = (const struct sockaddr_in *)ai->ai_addr;        tcp_floor->port = sin->sin_port;        ipv4_floor->ipv4addr = sin->sin_addr.s_addr;    }    else    {        ERR("unexpected protocol family %d\n", ai->ai_family);        return 0;    }    freeaddrinfo(ai);    return size;}static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *tower_data,                                                         size_t tower_size,                                                         char **networkaddr,                                                         char **endpoint){    const twr_tcp_floor_t *tcp_floor = (const twr_tcp_floor_t *)tower_data;    const twr_ipv4_floor_t *ipv4_floor;    struct in_addr in_addr;    TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);    if (tower_size < sizeof(*tcp_floor))        return EPT_S_NOT_REGISTERED;    tower_data += sizeof(*tcp_floor);    tower_size -= sizeof(*tcp_floor);    if (tower_size < sizeof(*ipv4_floor))        return EPT_S_NOT_REGISTERED;    ipv4_floor = (const twr_ipv4_floor_t *)tower_data;    if ((tcp_floor->count_lhs != sizeof(tcp_floor->protid)) ||        (tcp_floor->protid != EPM_PROTOCOL_TCP) ||        (tcp_floor->count_rhs != sizeof(tcp_floor->port)) ||        (ipv4_floor->count_lhs != sizeof(ipv4_floor->protid)) ||        (ipv4_floor->protid != EPM_PROTOCOL_IP) ||        (ipv4_floor->count_rhs != sizeof(ipv4_floor->ipv4addr)))        return EPT_S_NOT_REGISTERED;    if (endpoint)    {        *endpoint = I_RpcAllocate(6 /* sizeof("65535") + 1 */);        if (!*endpoint)            return RPC_S_OUT_OF_RESOURCES;        sprintf(*endpoint, "%u", ntohs(tcp_floor->port));    }    if (networkaddr)    {        *networkaddr = I_RpcAllocate(INET_ADDRSTRLEN);        if (!*networkaddr)        {            if (endpoint)            {                I_RpcFree(*endpoint);                *endpoint = NULL;            }            return RPC_S_OUT_OF_RESOURCES;        }        in_addr.s_addr = ipv4_floor->ipv4addr;        if (!inet_ntop(AF_INET, &in_addr, *networkaddr, INET_ADDRSTRLEN))        {            ERR("inet_ntop: %s\n", strerror(errno));            I_RpcFree(*networkaddr);            *networkaddr = NULL;            if (endpoint)            {                I_RpcFree(*endpoint);                *endpoint = NULL;            }            return EPT_S_NOT_REGISTERED;        }    }    return RPC_S_OK;}typedef struct _RpcServerProtseq_sock{    RpcServerProtseq common;    int mgr_event_rcv;    int mgr_event_snd;} RpcServerProtseq_sock;static RpcServerProtseq *rpcrt4_protseq_sock_alloc(void){    RpcServerProtseq_sock *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps));    if (ps)    {        int fds[2];        u_long blocking;        if (!socketpair(PF_UNIX, SOCK_DGRAM, 0, fds))        {            blocking = 1;            ioctlsocket(fds[0], FIONBIO, &blocking);            ioctlsocket(fds[1], FIONBIO, &blocking);            ps->mgr_event_rcv = fds[0];            ps->mgr_event_snd = fds[1];        }        else        {            ERR("socketpair failed with error %s\n", strerror(errno));            HeapFree(GetProcessHeap(), 0, ps);            return NULL;        }    }    return &ps->common;}static void rpcrt4_protseq_sock_signal_state_changed(RpcServerProtseq *protseq){    RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);    char dummy = 1;    write(sockps->mgr_event_snd, &dummy, sizeof(dummy));}static void *rpcrt4_protseq_sock_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count){    struct pollfd *poll_info = prev_array;    RpcConnection_tcp *conn;    RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);    EnterCriticalSection(&protseq->cs);        /* open and count connections */    *count = 1;    conn = (RpcConnection_tcp *)protseq->conn;    while (conn) {        if (conn->sock != -1)            (*count)++;        conn = (RpcConnection_tcp *)conn->common.Next;    }        /* make array of connections */    if (poll_info)        poll_info = HeapReAlloc(GetProcessHeap(), 0, poll_info, *count*sizeof(*poll_info));    else        poll_info = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(*poll_info));    if (!poll_info)    {        ERR("couldn't allocate poll_info\n");        LeaveCriticalSection(&protseq->cs);        return NULL;    }    poll_info[0].fd = sockps->mgr_event_rcv;    poll_info[0].events = POLLIN;    *count = 1;    conn =  CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);    while (conn) {        if (conn->sock != -1)        {            poll_info[*count].fd = conn->sock;            poll_info[*count].events = POLLIN;            (*count)++;        }        conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);    }    LeaveCriticalSection(&protseq->cs);    return poll_info;}static void rpcrt4_protseq_sock_free_wait_array(RpcServerProtseq *protseq, void *array){    HeapFree(GetProcessHeap(), 0, array);}static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array){    struct pollfd *poll_info = wait_array;    int ret, i;    RpcConnection *cconn;    RpcConnection_tcp *conn;        if (!poll_info)        return -1;    ret = poll(poll_info, count, -1);    if (ret < 0)    {        ERR("poll failed with error %d\n", ret);        return -1;    }    for (i = 0; i < count; i++)        if (poll_info[i].revents & POLLIN)        {            /* RPC server event */            if (i == 0)            {                char dummy;                read(poll_info[0].fd, &dummy, sizeof(dummy));                return 0;            }            /* find which connection got a RPC */            EnterCriticalSection(&protseq->cs);            conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);            while (conn) {                if (poll_info[i].fd == conn->sock) break;                conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);            }            cconn = NULL;            if (conn)                RPCRT4_SpawnConnection(&cconn, &conn->common);            else                ERR("failed to locate connection for fd %d\n", poll_info[i].fd);            LeaveCriticalSection(&protseq->cs);            if (cconn)                RPCRT4_new_client(cconn);            else                return -1;        }    return 1;}static const struct connection_ops conn_protseq_list[] = {  { "ncacn_np",    { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_SMB },    rpcrt4_conn_np_alloc,    rpcrt4_ncacn_np_open,    rpcrt4_ncacn_np_handoff,    rpcrt4_conn_np_read,    rpcrt4_conn_np_write,    rpcrt4_conn_np_close,    rpcrt4_ncacn_np_get_top_of_tower,    rpcrt4_ncacn_np_parse_top_of_tower,  },  { "ncalrpc",    { EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_PIPE },    rpcrt4_conn_np_alloc,    rpcrt4_ncalrpc_open,    rpcrt4_ncalrpc_handoff,    rpcrt4_conn_np_read,    rpcrt4_conn_np_write,    rpcrt4_conn_np_close,    rpcrt4_ncalrpc_get_top_of_tower,    rpcrt4_ncalrpc_parse_top_of_tower,  },  { "ncacn_ip_tcp",    { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_TCP },    rpcrt4_conn_tcp_alloc,    rpcrt4_ncacn_ip_tcp_open,    rpcrt4_conn_tcp_handoff,    rpcrt4_conn_tcp_read,    rpcrt4_conn_tcp_write,    rpcrt4_conn_tcp_close,    rpcrt4_ncacn_ip_tcp_get_top_of_tower,    rpcrt4_ncacn_ip_tcp_parse_top_of_tower,  }};static const struct protseq_ops protseq_list[] ={    {        "ncacn_np",        rpcrt4_protseq_np_alloc,        rpcrt4_protseq_np_signal_state_changed,        rpcrt4_protseq_np_get_wait_array,        rpcrt4_protseq_np_free_wait_array,        rpcrt4_protseq_np_wait_for_new_connection,        rpcrt4_protseq_ncacn_np_open_endpoint,    },    {        "ncalrpc",        rpcrt4_protseq_np_alloc,        rpcrt4_protseq_np_signal_state_changed,        rpcrt4_protseq_np_get_wait_array,        rpcrt4_protseq_np_free_wait_array,        rpcrt4_protseq_np_wait_for_new_connection,        rpcrt4_protseq_ncalrpc_open_endpoint,    },    {        "ncacn_ip_tcp",        rpcrt4_protseq_sock_alloc,        rpcrt4_protseq_sock_signal_state_changed,        rpcrt4_protseq_sock_get_wait_array,        rpcrt4_protseq_sock_free_wait_array,        rpcrt4_protseq_sock_wait_for_new_connection,        rpcrt4_protseq_ncacn_ip_tcp_open_endpoint,    },};#define ARRAYSIZE(a) (sizeof((a)) / sizeof((a)[0]))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -