/*********************************************************************** * 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; }
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; }