in win32/src/socket_transport_win32.c [555:645]
int socket_transport_listen(SOCKET_TRANSPORT_HANDLE socket_transport, uint16_t port)
{
int result;
// Codes_SOCKET_TRANSPORT_WIN32_09_055: [ If socket_transport is NULL, socket_transport_listen shall fail and return a non-zero value. ]
// Codes_SOCKET_TRANSPORT_WIN32_09_056: [ If port is 0, socket_transport_listen shall fail and return a non-zero value. ]
if (socket_transport == NULL ||
port == 0)
{
LogError("Invalid arguments: SOCKET_TRANSPORT_HANDLE socket_transport: %p, uint16_t port: %" PRIu16 "",
socket_transport, port);
result = MU_FAILURE;
}
else
{
// Codes_SOCKET_TRANSPORT_WIN32_09_057: [ If the transport type is not SOCKET_BINDING, socket_transport_listen shall fail and return a non-zero value. ]
if (socket_transport->type != SOCKET_BINDING)
{
LogError("Invalid socket type for this API expected: SOCKET_BINDING, actual: %" PRI_MU_ENUM, MU_ENUM_VALUE(SOCKET_TYPE, socket_transport->type));
result = MU_FAILURE;
}
else
{
// Codes_SOCKET_TRANSPORT_WIN32_09_058: [ socket_transport_listen shall call sm_open_begin to begin the open. ]
SM_RESULT open_result = sm_open_begin(socket_transport->sm);
// Codes_SOCKET_TRANSPORT_WIN32_09_059: [ If sm_open_begin does not return SM_EXEC_GRANTED, socket_transport_listen shall fail and return a non-zero value. ]
if (open_result != SM_EXEC_GRANTED)
{
LogError("sm_open_begin failed with %" PRI_MU_ENUM, MU_ENUM_VALUE(SM_RESULT, open_result));
result = MU_FAILURE;
}
else
{
// Codes_SOCKET_TRANSPORT_WIN32_09_060: [ socket_transport_listen shall call socket with the params AF_INET, SOCK_STREAM and IPPROTO_TCP. ]
socket_transport->socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (socket_transport->socket == INVALID_SOCKET)
{
LogLastError("Could not create socket");
result = MU_FAILURE;
}
else
{
u_long iMode = 1;
struct sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = INADDR_ANY;
service.sin_port = htons(port);
// Codes_SOCKET_TRANSPORT_WIN32_09_061: [ socket_transport_listen shall bind to the socket by calling bind. ]
if (bind(socket_transport->socket, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR)
{
LogLastError("Could not bind socket, port=%" PRIu16 "", port);
result = MU_FAILURE;
}
// Codes_SOCKET_TRANSPORT_WIN32_09_065: [ sock_transport_listen shall set listening socket in non-blocking mode by calling ioctlsocket. ]
else if (ioctlsocket(socket_transport->socket, FIONBIO, &iMode) != 0)
{
LogLastError("Could not set listening socket in non-blocking mode");
result = MU_FAILURE;
}
else
{
// Codes_SOCKET_TRANSPORT_WIN32_09_062: [ socket_transport_listen shall start listening to incoming connection by calling listen. ]
if (listen(socket_transport->socket, SOMAXCONN) == SOCKET_ERROR)
{
LogLastError("Could not start listening for connections");
result = MU_FAILURE;
}
else
{
// Codes_SOCKET_TRANSPORT_WIN32_09_063: [ If successful socket_transport_listen shall call sm_open_end with true. ]
sm_open_end(socket_transport->sm, true);
result = 0;
goto all_ok;
}
}
// Codes_SOCKET_TRANSPORT_WIN32_09_066: [ socket_transport_listen shall call closesocket. ]
(void)closesocket(socket_transport->socket);
// Codes_SOCKET_TRANSPORT_WIN32_09_064: [ If any failure is encountered, socket_transport_listen shall call sm_open_end with false, fail and return a non-zero value. ]
sm_open_end(socket_transport->sm, false);
}
}
}
}
all_ok:
return result;
}