void IsoClientConnection_associate(IsoClientConnection self, IsoConnectionParameters* params, ByteBuffer* payload) { Socket socket = TcpSocket_create(); self->socket = socket; if (!Socket_connect(socket, params->hostname, params->tcpPort)) goto returnError; self->cotpBuf = malloc(ISO_CLIENT_BUFFER_SIZE); self->cotpBuffer = calloc(1, sizeof(ByteBuffer)); ByteBuffer_wrap(self->cotpBuffer, self->cotpBuf, 0, ISO_CLIENT_BUFFER_SIZE); self->cotpConnection = calloc(1, sizeof(CotpConnection)); CotpConnection_init(self->cotpConnection, socket, self->cotpBuffer); /* COTP handshake */ CotpIndication cotpIndication = CotpConnection_sendConnectionRequestMessage(self->cotpConnection); cotpIndication = CotpConnection_parseIncomingMessage(self->cotpConnection); if (cotpIndication != CONNECT_INDICATION) goto returnError; /* Upper layers handshake */ AcseConnection acse; ByteBuffer acseBuffer; ByteBuffer_wrap(&acseBuffer, self->buffer1, 0, ISO_CLIENT_BUFFER_SIZE); AcseConnection_init(&acse); if (params != NULL) AcseConnection_setAuthenticationParameter(&acse, params->acseAuthParameter); AcseConnection_createAssociateRequestMessage(&acse, &acseBuffer, payload); ByteBuffer presentationBuffer; ByteBuffer_wrap(&presentationBuffer, self->buffer2, 0, ISO_CLIENT_BUFFER_SIZE); self->presentation = calloc(1, sizeof(IsoPresentation)); IsoPresentation_init(self->presentation); IsoPresentation_createConnectPdu(self->presentation, &presentationBuffer, &acseBuffer); ByteBuffer sessionBuffer; ByteBuffer_wrap(&sessionBuffer, self->buffer1, 0, ISO_CLIENT_BUFFER_SIZE); self->session = calloc(1, sizeof(IsoSession)); IsoSession_init(self->session); IsoSession_createConnectSpdu(self->session, &sessionBuffer, ByteBuffer_getSize(&presentationBuffer)); ByteBuffer_append(&sessionBuffer, ByteBuffer_getBuffer(&presentationBuffer), ByteBuffer_getSize(&presentationBuffer)); CotpConnection_sendDataMessage(self->cotpConnection, &sessionBuffer); cotpIndication = CotpConnection_parseIncomingMessage(self->cotpConnection); if (cotpIndication != DATA_INDICATION) goto returnError; IsoSessionIndication sessionIndication; sessionIndication = IsoSession_parseMessage(self->session, CotpConnection_getPayload(self->cotpConnection)); if (sessionIndication != SESSION_CONNECT) { if (DEBUG) printf("IsoClientConnection_associate: no session connect indication\n"); goto returnError; } IsoPresentationIndication presentationIndication; presentationIndication = IsoPresentation_parseAcceptMessage(self->presentation, IsoSession_getUserData(self->session)); if (presentationIndication != PRESENTATION_OK) { if (DEBUG) printf("IsoClientConnection_associate: no presentation ok indication\n"); goto returnError; } AcseIndication acseIndication; acseIndication = AcseConnection_parseMessage(&acse, &self->presentation->nextPayload); if (acseIndication != ACSE_ASSOCIATE) { if (DEBUG) printf("IsoClientConnection_associate: no ACSE_ASSOCIATE indication\n"); goto returnError; } ByteBuffer acsePayload; //TODO allocate buffer dynamically??? ByteBuffer_wrap(&acsePayload, acse.userDataBuffer, acse.userDataBufferSize, 1024); self->callback(ISO_IND_ASSOCIATION_SUCCESS, self->callbackParameter, &acsePayload); self->state = STATE_ASSOCIATED; AcseConnection_destroy(&acse); self->thread = Thread_create(connectionHandlingThread, self, false); Thread_start(self->thread); return; returnError: self->callback(ISO_IND_ASSOCIATION_FAILED, self->callbackParameter, &acsePayload); AcseConnection_destroy(&acse); self->state = STATE_ERROR; return; }
static void handleTcpConnection(IsoConnection self) { if (DEBUG_ISO_SERVER) printf("ISO_SERVER: connection %p started\n", self); CotpIndication cotpIndication; IsoSessionIndication sIndication; AcseIndication aIndication; AcseConnection acseConnection; ByteBuffer receiveBuffer; self->cotpConnection = (CotpConnection*) calloc(1, sizeof(CotpConnection)); CotpConnection_init(self->cotpConnection, self->socket, &receiveBuffer); self->session = (IsoSession*) calloc(1, sizeof(IsoSession)); IsoSession_init(self->session); self->presentation = (IsoPresentation*) calloc(1, sizeof(IsoPresentation)); IsoPresentation_init(self->presentation); AcseConnection_init(&acseConnection, IsoServer_getAuthenticator(self->isoServer), IsoServer_getAuthenticatorParameter(self->isoServer)); while (self->msgRcvdHandlerParameter == NULL) Thread_sleep(1); if (DEBUG_ISO_SERVER) printf("ISO_SERVER: IsoConnection: Start to handle connection for client %s\n", self->clientAddress); while (self->state == ISO_CON_STATE_RUNNING) { ByteBuffer_wrap(&receiveBuffer, self->receiveBuffer, 0, RECEIVE_BUF_SIZE); cotpIndication = CotpConnection_parseIncomingMessage(self->cotpConnection); switch (cotpIndication) { case CONNECT_INDICATION: if (DEBUG_ISO_SERVER) printf("ISO_SERVER: COTP connection indication\n"); Semaphore_wait(self->conMutex); CotpConnection_sendConnectionResponseMessage(self->cotpConnection); Semaphore_post(self->conMutex); break; case DATA_INDICATION: { if (DEBUG_ISO_SERVER) printf("ISO_SERVER: COTP data indication\n"); ByteBuffer* cotpPayload = CotpConnection_getPayload(self->cotpConnection); sIndication = IsoSession_parseMessage(self->session, cotpPayload); ByteBuffer* sessionUserData = IsoSession_getUserData(self->session); switch (sIndication) { case SESSION_CONNECT: if (DEBUG_ISO_SERVER) printf("ISO_SERVER: iso_connection: session connect indication\n"); if (IsoPresentation_parseConnect(self->presentation, sessionUserData)) { if (DEBUG_ISO_SERVER) printf("ISO_SERVER: iso_connection: presentation ok\n"); ByteBuffer* acseBuffer = &(self->presentation->nextPayload); aIndication = AcseConnection_parseMessage(&acseConnection, acseBuffer); self->securityToken = acseConnection.securityToken; if (aIndication == ACSE_ASSOCIATE) { Semaphore_wait(self->conMutex); if (DEBUG_ISO_SERVER) printf("ISO_SERVER: cotp_server: acse associate\n"); ByteBuffer mmsRequest; ByteBuffer_wrap(&mmsRequest, acseConnection.userDataBuffer, acseConnection.userDataBufferSize, acseConnection.userDataBufferSize); ByteBuffer mmsResponseBuffer; /* new */ ByteBuffer_wrap(&mmsResponseBuffer, self->sendBuffer, 0, SEND_BUF_SIZE); self->msgRcvdHandler(self->msgRcvdHandlerParameter, &mmsRequest, &mmsResponseBuffer); struct sBufferChain mmsBufferPartStruct; BufferChain mmsBufferPart = &mmsBufferPartStruct; BufferChain_init(mmsBufferPart, mmsResponseBuffer.size, mmsResponseBuffer.size, NULL, self->sendBuffer); if (mmsResponseBuffer.size > 0) { if (DEBUG_ISO_SERVER) printf("iso_connection: application payload size: %i\n", mmsResponseBuffer.size); struct sBufferChain acseBufferPartStruct; BufferChain acseBufferPart = &acseBufferPartStruct; acseBufferPart->buffer = self->sendBuffer + mmsBufferPart->length; acseBufferPart->partMaxLength = SEND_BUF_SIZE - mmsBufferPart->length; AcseConnection_createAssociateResponseMessage(&acseConnection, ACSE_RESULT_ACCEPT, acseBufferPart, mmsBufferPart); struct sBufferChain presentationBufferPartStruct; BufferChain presentationBufferPart = &presentationBufferPartStruct; presentationBufferPart->buffer = self->sendBuffer + acseBufferPart->length; presentationBufferPart->partMaxLength = SEND_BUF_SIZE - acseBufferPart->length; IsoPresentation_createCpaMessage(self->presentation, presentationBufferPart, acseBufferPart); struct sBufferChain sessionBufferPartStruct; BufferChain sessionBufferPart = &sessionBufferPartStruct; sessionBufferPart->buffer = self->sendBuffer + presentationBufferPart->length; sessionBufferPart->partMaxLength = SEND_BUF_SIZE - presentationBufferPart->length; IsoSession_createAcceptSpdu(self->session, sessionBufferPart, presentationBufferPart); CotpConnection_sendDataMessage(self->cotpConnection, sessionBufferPart); } else { if (DEBUG_ISO_SERVER) printf( "ISO_SERVER: iso_connection: association error. No response from application!\n"); } Semaphore_post(self->conMutex); } else { if (DEBUG_ISO_SERVER) printf("ISO_SERVER: iso_connection: acse association failed\n"); self->state = ISO_CON_STATE_STOPPED; } } break; case SESSION_DATA: if (DEBUG_ISO_SERVER) printf("ISO_SERVER: iso_connection: session data indication\n"); if (!IsoPresentation_parseUserData(self->presentation, sessionUserData)) { if (DEBUG_ISO_SERVER) printf("ISO_SERVER: cotp_server: presentation error\n"); self->state = ISO_CON_STATE_STOPPED; break; } if (self->presentation->nextContextId == self->presentation->mmsContextId) { if (DEBUG_ISO_SERVER) printf("ISO_SERVER: iso_connection: mms message\n"); ByteBuffer* mmsRequest = &(self->presentation->nextPayload); ByteBuffer mmsResponseBuffer; IsoServer_userLock(self->isoServer); Semaphore_wait(self->conMutex); ByteBuffer_wrap(&mmsResponseBuffer, self->sendBuffer, 0, SEND_BUF_SIZE); self->msgRcvdHandler(self->msgRcvdHandlerParameter, mmsRequest, &mmsResponseBuffer); if (mmsResponseBuffer.size > 0) { struct sBufferChain mmsBufferPartStruct; BufferChain mmsBufferPart = &mmsBufferPartStruct; BufferChain_init(mmsBufferPart, mmsResponseBuffer.size, mmsResponseBuffer.size, NULL, self->sendBuffer); struct sBufferChain presentationBufferPartStruct; BufferChain presentationBufferPart = &presentationBufferPartStruct; presentationBufferPart->buffer = self->sendBuffer + mmsBufferPart->length; presentationBufferPart->partMaxLength = SEND_BUF_SIZE - mmsBufferPart->length; IsoPresentation_createUserData(self->presentation, presentationBufferPart, mmsBufferPart); struct sBufferChain sessionBufferPartStruct; BufferChain sessionBufferPart = &sessionBufferPartStruct; sessionBufferPart->buffer = self->sendBuffer + presentationBufferPart->length; sessionBufferPart->partMaxLength = SEND_BUF_SIZE - presentationBufferPart->length; IsoSession_createDataSpdu(self->session, sessionBufferPart, presentationBufferPart); CotpConnection_sendDataMessage(self->cotpConnection, sessionBufferPart); } Semaphore_post(self->conMutex); IsoServer_userUnlock(self->isoServer); } else { if (DEBUG_ISO_SERVER) printf("ISO_SERVER: iso_connection: unknown presentation layer context!"); } break; case SESSION_FINISH: if (DEBUG_ISO_SERVER) printf("ISO_SERVER: iso_connection: session finish indication\n"); if (IsoPresentation_parseUserData(self->presentation, sessionUserData)) { if (DEBUG_ISO_SERVER) printf("ISO_SERVER: iso_connection: presentation ok\n"); struct sBufferChain acseBufferPartStruct; BufferChain acseBufferPart = &acseBufferPartStruct; acseBufferPart->buffer = self->sendBuffer; acseBufferPart->partMaxLength = SEND_BUF_SIZE; AcseConnection_createReleaseResponseMessage(&acseConnection, acseBufferPart); struct sBufferChain presentationBufferPartStruct; BufferChain presentationBufferPart = &presentationBufferPartStruct; presentationBufferPart->buffer = self->sendBuffer + acseBufferPart->length; presentationBufferPart->partMaxLength = SEND_BUF_SIZE - acseBufferPart->length; IsoPresentation_createUserDataACSE(self->presentation, presentationBufferPart, acseBufferPart); struct sBufferChain sessionBufferPartStruct; BufferChain sessionBufferPart = &sessionBufferPartStruct; sessionBufferPart->buffer = self->sendBuffer + presentationBufferPart->length; sessionBufferPart->partMaxLength = SEND_BUF_SIZE - presentationBufferPart->length; IsoSession_createDisconnectSpdu(self->session, sessionBufferPart, presentationBufferPart); CotpConnection_sendDataMessage(self->cotpConnection, sessionBufferPart); } //TODO else send ABORT message break; case SESSION_ABORT: self->state = ISO_CON_STATE_STOPPED; break; case SESSION_ERROR: self->state = ISO_CON_STATE_STOPPED; break; default: /* illegal state */ self->state = ISO_CON_STATE_STOPPED; break; } } break; case ERROR: if (DEBUG_ISO_SERVER) printf("ISO_SERVER: Connection closed\n"); self->state = ISO_CON_STATE_STOPPED; break; default: if (DEBUG_ISO_SERVER) printf("ISO_SERVER: COTP Unknown Indication: %i\n", cotpIndication); self->state = ISO_CON_STATE_STOPPED; break; } } IsoServer_closeConnection(self->isoServer, self); if (self->socket != NULL) Socket_destroy(self->socket); free(self->session); free(self->presentation); AcseConnection_destroy(&acseConnection); CotpConnection_destroy(self->cotpConnection); free(self->cotpConnection); Semaphore_destroy(self->conMutex); free(self->receiveBuffer); free(self->sendBuffer); free(self->clientAddress); IsoServer isoServer = self->isoServer; free(self); if (DEBUG_ISO_SERVER) printf("ISO_SERVER: connection %p closed\n", self); private_IsoServer_decreaseConnectionCounter(isoServer); }
static void handleTcpConnection(IsoConnection self) { CotpIndication cotpIndication; CotpConnection cotpConnection; IsoSessionIndication sIndication; IsoSession session; IsoPresentation presentation; IsoPresentationIndication pIndication; AcseIndication aIndication; AcseConnection acseConnection; ByteBuffer receiveBuffer; ByteBuffer responseBuffer1; ByteBuffer responseBuffer2; CotpConnection_init(&cotpConnection, self->socket, &receiveBuffer); IsoSession_init(&session); IsoPresentation_init(&presentation); AcseConnection_init(&acseConnection); AcseConnection_setAuthenticationParameter(&acseConnection, IsoServer_getAuthenticationParameter(self->isoServer)); while (self->msgRcvdHandlerParameter == NULL) Thread_sleep(1); printf("IsoConnection: state = RUNNING. Start to handle connection\n"); while (self->state == ISO_CON_STATE_RUNNING) { ByteBuffer_wrap(&receiveBuffer, self->receive_buf, 0, RECEIVE_BUF_SIZE); ByteBuffer_wrap(&responseBuffer1, self->send_buf_1, 0, SEND_BUF_SIZE); ByteBuffer_wrap(&responseBuffer2, self->send_buf_2, 0, SEND_BUF_SIZE); cotpIndication = CotpConnection_parseIncomingMessage(&cotpConnection); switch (cotpIndication) { case CONNECT_INDICATION: if (DEBUG) printf("COTP connection indication\n"); CotpConnection_sendConnectionResponseMessage(&cotpConnection); break; case DATA_INDICATION: if (DEBUG) printf("COTP data indication\n"); ByteBuffer* cotpPayload = CotpConnection_getPayload(&cotpConnection); sIndication = IsoSession_parseMessage(&session, cotpPayload); ByteBuffer* sessionUserData = IsoSession_getUserData(&session); switch (sIndication) { case SESSION_CONNECT: if (DEBUG) printf("cotp_server: session connect indication\n"); pIndication = IsoPresentation_parseConnect(&presentation, sessionUserData); if (pIndication == PRESENTATION_OK) { if (DEBUG) printf("cotp_server: presentation ok\n"); ByteBuffer* acseBuffer = &(presentation.nextPayload); aIndication = AcseConnection_parseMessage(&acseConnection, acseBuffer); if (aIndication == ACSE_ASSOCIATE) { if (DEBUG) printf("cotp_server: acse associate\n"); ByteBuffer mmsRequest; ByteBuffer_wrap(&mmsRequest, acseConnection.userDataBuffer, acseConnection.userDataBufferSize, acseConnection.userDataBufferSize); self->msgRcvdHandler(self->msgRcvdHandlerParameter, &mmsRequest, &responseBuffer1); if (responseBuffer1.size > 0) { if (DEBUG) printf("cotp_server: application payload size: %i\n", responseBuffer1.size); AcseConnection_createAssociateResponseMessage(&acseConnection, &responseBuffer2, &responseBuffer1); responseBuffer1.size = 0; IsoPresentation_createCpaMessage(&presentation, &responseBuffer1, &responseBuffer2); responseBuffer2.size = 0; IsoSession_createAcceptSpdu(&session, &responseBuffer2, responseBuffer1.size); ByteBuffer_append(&responseBuffer2, responseBuffer1.buffer, responseBuffer1.size); CotpConnection_sendDataMessage(&cotpConnection, &responseBuffer2); break; } else { if (DEBUG) printf("cotp_server: association error. No response from application!\n"); } } else { if (DEBUG) printf("cotp_server: acse association failed\n"); self->state = ISO_CON_STATE_STOPPED; } } break; case SESSION_DATA: if (DEBUG) printf("cotp_server: session data indication\n"); pIndication = IsoPresentation_parseUserData(&presentation, sessionUserData); if (pIndication == PRESENTATION_ERROR) { if (DEBUG) printf("cotp_server: presentation error\n"); self->state = ISO_CON_STATE_STOPPED; break; } if (presentation.nextContextId == 3) { if (DEBUG) printf("cotp_server: mms message\n"); ByteBuffer* mmsRequest = &(presentation.nextPayload); self->msgRcvdHandler(self->msgRcvdHandlerParameter, mmsRequest, &responseBuffer1); IsoPresentation_createUserData(&presentation, &responseBuffer2, &responseBuffer1); responseBuffer1.size = 0; IsoSession_createDataSpdu(&session, &responseBuffer1); ByteBuffer_append(&responseBuffer1, responseBuffer2.buffer, responseBuffer2.size); CotpConnection_sendDataMessage(&cotpConnection, &responseBuffer1); } break; case SESSION_ERROR: self->state = ISO_CON_STATE_STOPPED; break; } break; case ERROR: if (DEBUG) printf("COTP protocol error\n"); self->state = ISO_CON_STATE_STOPPED; break; default: if (DEBUG) printf("COTP Unknown Indication: %i\n", cotpIndication); self->state = ISO_CON_STATE_STOPPED; break; } } Socket_destroy(self->socket); //if (DEBUG) printf("IsoConnection: connection closed!\n"); AcseConnection_destroy(&acseConnection); IsoServer_closeConnection(self->isoServer, self); CotpConnection_destroy(&cotpConnection); }