예제 #1
0
/***********************************************************************
 *           I_RpcSendReceive [RPCRT4.@]
 *
 * Sends a message to the server and receives the response.
 *
 * PARAMS
 *  pMsg [I/O] RPC message information.
 *
 * RETURNS
 *  Success: RPC_S_OK.
 *  Failure: Any error code.
 *
 * NOTES
 *  The buffer must have been allocated with I_RpcGetBuffer().
 *
 * SEE ALSO
 *  I_RpcGetBuffer(), I_RpcSend(), I_RpcReceive().
 */
RPC_STATUS WINAPI I_RpcSendReceive(PRPC_MESSAGE pMsg)
{
	RpcBinding* bind = (RpcBinding*)pMsg->Handle;
	RpcConnection * conn = (RpcConnection *)pMsg->ReservedForRuntime;
	ITgmRpcConnection* theConn = conn->rpc_connection;
	void* res_buf = 0;
	ULONG res_len = 0;
	ipc_client_memory_free_fun_t res_free = NULL;


	RpcPktHdr *hdr = RPCRT4_BuildRequestHeader(pMsg->DataRepresentation,
		pMsg->BufferLength,
		pMsg->ProcNum & ~RPC_FLAGS_VALID_BIT,
		&bind->ObjectUuid);

	hdr->common.frag_len += pMsg->BufferLength;

	char* pkt =  (char*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,hdr->common.frag_len+1);
	memcpy(pkt,hdr,hdr->common.frag_len-pMsg->BufferLength);
	memcpy(pkt+hdr->common.frag_len-pMsg->BufferLength,pMsg->Buffer,pMsg->BufferLength);


	HRESULT hr = theConn->SendSyncRequestEx(pkt,hdr->common.frag_len,&res_buf,&res_len,&res_free,0);
	HeapFree(GetProcessHeap(),0,pkt);
	HeapFree(GetProcessHeap(),0,hdr);
	HeapFree(GetProcessHeap(),0,pMsg->Buffer);

	if(SUCCEEDED(hr))
	{
		CRpcUnpacker theUnPacket(res_buf,res_len);
		pMsg->BufferLength = theUnPacket.get_BufferLength();
		pMsg->Buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,pMsg->BufferLength);
		memcpy(pMsg->Buffer,theUnPacket.get_BufferPtr(),pMsg->BufferLength);
		res_free(res_buf);
	}else {
		RPCRT4_DestroyConnection(conn);
		pMsg->ReservedForRuntime = NULL;
	}

	return RPC_S_OK;
}
예제 #2
0
static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *protseq, LPSTR endpoint)
{
    RPC_STATUS status = RPC_S_CANT_CREATE_ENDPOINT;
    int sock;
    int ret;
    struct addrinfo *ai;
    struct addrinfo *ai_cur;
    struct addrinfo hints;
    RpcConnection *first_connection = NULL;

    TRACE("(%p, %s)\n", protseq, endpoint);

    hints.ai_flags          = AI_PASSIVE /* for non-localhost addresses */;
    hints.ai_family         = PF_UNSPEC;
    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(NULL, endpoint, &hints, &ai);
    if (ret)
    {
        ERR("getaddrinfo for port %s failed: %s\n", endpoint,
            gai_strerror(ret));
        if ((ret == EAI_SERVICE) || (ret == EAI_NONAME))
            return RPC_S_INVALID_ENDPOINT_FORMAT;
        return RPC_S_CANT_CREATE_ENDPOINT;
    }

    for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next)
    {
        RpcConnection_tcp *tcpc;
        RPC_STATUS create_status;

        if (TRACE_ON(rpc))
        {
            char host[256];
            char service[256];
            getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen,
                        host, sizeof(host), service, sizeof(service),
                        NI_NUMERICHOST | NI_NUMERICSERV);
            TRACE("trying %s:%s\n", host, service);
        }

        sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol);
        if (sock == -1)
        {
            WARN("socket() failed: %s\n", strerror(errno));
            status = RPC_S_CANT_CREATE_ENDPOINT;
            continue;
        }

        ret = bind(sock, ai_cur->ai_addr, ai_cur->ai_addrlen);
        if (ret < 0)
        {
            WARN("bind failed: %s\n", strerror(errno));
            closesocket(sock);
            if (errno == EADDRINUSE)
              status = RPC_S_DUPLICATE_ENDPOINT;
            else
              status = RPC_S_CANT_CREATE_ENDPOINT;
            continue;
        }
        create_status = RPCRT4_CreateConnection((RpcConnection **)&tcpc, TRUE,
                                                protseq->Protseq, NULL,
                                                endpoint, NULL, NULL, NULL);
        if (create_status != RPC_S_OK)
        {
            closesocket(sock);
            status = create_status;
            continue;
        }

        tcpc->sock = sock;
        ret = listen(sock, protseq->MaxCalls);
        if (ret < 0)
        {
            WARN("listen failed: %s\n", strerror(errno));
            RPCRT4_DestroyConnection(&tcpc->common);
            status = RPC_S_OUT_OF_RESOURCES;
            continue;
        }
        /* 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...)
         */
        ret = fcntl(sock, F_SETFL, O_NONBLOCK);
        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;
}