/** * @file kTcpServer.cpp * * @internal * Copyright (C) 2008-2021 by LMI Technologies Inc. * Licensed under the MIT License. * Redistributed files must retain the above copyright notice. */ #include #include #include kBeginClassEx(k, kTcpServer) kAddPrivateVMethod(kTcpServer, kObject, VRelease) kEndClassEx() kFx(kStatus) kTcpServer_Construct(kTcpServer* server, kIpVersion ipVersion, kAlloc allocator) { kAlloc alloc = kAlloc_Fallback(allocator); kType type = kTypeOf(kTcpServer); kStatus status; kCheck(kAlloc_GetObject(alloc, type, server)); if (!kSuccess(status = xkTcpServer_Init(*server, type, ipVersion, alloc))) { kAlloc_FreeRef(alloc, server); } return status; } kFx(kStatus) xkTcpServer_Init(kTcpServer server, kType type, kIpVersion ipVersion, kAlloc allocator) { kObjR(kTcpServer, server); kStatus status; kCheck(kObject_Init(server, type, allocator)); obj->socket = kNULL; obj->clientWriteBufferSize = -1; obj->clientReadBufferSize = -1; kTry { kTest(kSocket_Construct(&obj->socket, ipVersion, kSOCKET_TYPE_TCP, allocator)); } kCatch(&status) { xkTcpServer_VRelease(server); kEndCatch(status); } return kOK; } kFx(kStatus) xkTcpServer_VRelease(kTcpServer server) { kObj(kTcpServer, server); kCheck(kObject_Destroy(obj->socket)); kCheck(kObject_VRelease(server)); return kOK; } kFx(kStatus) kTcpServer_SetWriteBuffers(kTcpServer server, kSSize socketSize, kSSize clientSize) { kObj(kTcpServer, server); if (socketSize >= 0) { //SYS/BIOS (and possibly other systems) does not permit buffer sizes to be set after a //connection is accepted. The correct way to set the buffer size is to set the option on the //server socket and allow the option to be inherited by accepted sockets. kCheck(kSocket_SetWriteBuffer(obj->socket, (kSize)socketSize)); } obj->clientWriteBufferSize = clientSize; return kOK; } kFx(kStatus) kTcpServer_SetReadBuffers(kTcpServer server, kSSize socketSize, kSSize clientSize) { kObj(kTcpServer, server); if (socketSize >= 0) { //SYS/BIOS (and possibly other systems) does not permit buffer sizes to be set after a //connection is accepted. The correct way to set the buffer size is to set the option on the //server socket and allow the option to be inherited by accepted sockets. kCheck(kSocket_SetReadBuffer(obj->socket, (kSize)socketSize)); } obj->clientReadBufferSize = clientSize; return kOK; } kFx(kStatus) kTcpServer_Listen(kTcpServer server, kIpAddress address, k32u port, kSize backlog) { kObj(kTcpServer, server); kCheck(kSocket_Bind(obj->socket, address, port)); kCheck(kSocket_Listen(obj->socket, backlog)); return kOK; } kFx(kStatus) kTcpServer_Accept(kTcpServer server, k64u timeout, kTcpClient* client, kAlloc allocator) { kObj(kTcpServer, server); kSocket connection = kNULL; kStatus status; *client = kNULL; kTry { kTest(kSocket_Wait(obj->socket, timeout)); kTest(kSocket_Accept(obj->socket, &connection, allocator)); if (!kIsNull(connection)) { kTest(xkTcpClient_ConstructFromSocket(client, connection, allocator)); connection = kNULL; if (obj->clientWriteBufferSize >= 0) { kTest(kTcpClient_SetWriteBuffers(*client, -1, obj->clientWriteBufferSize)); } if (obj->clientReadBufferSize >= 0) { kTest(kTcpClient_SetReadBuffers(*client, -1, obj->clientReadBufferSize)); } } } kCatch(&status) { kObject_Destroy(connection); kDestroyRef(client); kEndCatch(status); } return kOK; } kFx(kStatus) kTcpServer_EnableReuseAddress(kTcpServer server, kBool reuse) { kObj(kTcpServer, server); return kSocket_EnableReuseAddress(obj->socket, reuse); } kFx(kSocket) kTcpServer_Socket(kTcpServer server) { kObj(kTcpServer, server); return obj->socket; } kFx(kStatus) kTcpServer_LocalEndPoint(kTcpServer server, kIpEndPoint* endPoint) { kObj(kTcpServer, server); return kSocket_LocalEndPoint(obj->socket, endPoint); }