static BaseType_t prvSendReply( xHTTPClient *pxClient, BaseType_t xCode ) { struct xTCP_SERVER *pxParent = pxClient->pxParent; BaseType_t xRc; // A normal command reply on the main socket (port 21) char *pcBuffer = pxParent->pcFileBuffer; xRc = snprintf( pcBuffer, sizeof( pxParent->pcFileBuffer ), "HTTP/1.1 %d %s\r\n" #if USE_HTML_CHUNKS "Transfer-Encoding: chunked\r\n" #endif "Content-Type: %s\r\n" "Connection: keep-alive\r\n" "%s\r\n", ( int ) xCode, webCodename (xCode), pxParent->pcContentsType[0] ? pxParent->pcContentsType : "text/html", pxParent->pcExtraContents ); pxParent->pcContentsType[0] = '\0'; pxParent->pcExtraContents[0] = '\0'; xRc = FreeRTOS_send( pxClient->xSocket, ( const void * ) pcBuffer, xRc, 0 ); pxClient->bits.bReplySent = pdTRUE; return xRc; }
int FreeRTOS_write(Network* n, unsigned char* buffer, int len, uint32_t timeout_ms) { portTickType xTicksToWait = timeout_ms / portTICK_RATE_MS; /* convert milliseconds to ticks */ xTimeOutType xTimeOut; int sentLen = 0; vTaskSetTimeOutState(&xTimeOut); /* Record the time at which this function was entered. */ FreeRTOS_setsockopt(n->my_socket, SOL_SOCKET, FREERTOS_SO_RCVTIMEO, &timeout_ms, sizeof(timeout_ms)); do { int rc = 0; rc = FreeRTOS_send(n->my_socket, buffer + sentLen, len - sentLen, 0); if (rc > 0) sentLen += rc; else if (rc < 0) { sentLen = rc; break; } } while (sentLen < len && xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE); return sentLen; }
static BaseType_t prvTcpWork( xTcpServer_t *pxTcpServer ) { BaseType_t lBytes, lReturned, lMayWrite; lMayWrite = FreeRTOS_maywrite( pxTcpServer->xSocket ); if( lMayWrite < 0 ) return lMayWrite; while( lMayWrite > 0 ) { lReturned = prvTcpSend( pxTcpServer ); if( lReturned < 0 ) return lReturned; if( lReturned == 0 ) break; lMayWrite = FreeRTOS_maywrite( pxTcpServer->xSocket ); if( lMayWrite < 0 ) return lMayWrite; } for( ; ; ) { /* Zero out the receive array so there is NULL at the end of the string when it is printed out. */ memset( cReceivedString, 0x00, sizeof( cReceivedString ) ); /* Receive data on the socket. */ lBytes = FreeRTOS_recv( pxTcpServer->xSocket, cReceivedString, sizeof( cReceivedString ), 0 ); if( lBytes <= 0 ) return lBytes; /* Return the received characters. */ if( lMayWrite > 0 && sbGetSize( pxTcpServer->pxSendData ) == 0 ) { /* The cirular buffer is empty, send the received data directly */ lReturned = FreeRTOS_send( pxTcpServer->xSocket, cReceivedString, lBytes, 0 ); if( lReturned < 0 ) { return -1; } if( lBytes > lReturned ) { /* Not all dta could be delivered, save them for later * FD_SET( eSELECT_WRITE ) will be called */ sbAdd( pxTcpServer->pxSendData, 0, cReceivedString + lReturned, lBytes - lReturned ); } lMayWrite = FreeRTOS_maywrite( pxTcpServer->xSocket ); if( lMayWrite < 0 ) return lMayWrite; } else { sbAdd( pxTcpServer->pxSendData, 0, cReceivedString, lBytes ); } } }
static BaseType_t prvTcpSend( xTcpServer_t *pxTcpServer ) { BaseType_t lBytes, lReturned, xReturn = 0; lBytes = sbGet( pxTcpServer->pxSendData, 0, cReceivedString, sizeof( cReceivedString ), pdTRUE ); if( lBytes ) { /* Send as much as possible, non-blocking */ lReturned = FreeRTOS_send( pxTcpServer->xSocket, cReceivedString, lBytes, 0 ); if( lReturned > 0 ) { xReturn = sbGet( pxTcpServer->pxSendData, 0, NULL, lReturned, pdFALSE ); } } return xReturn; }
void z80BiosConsoleIO(trapargs_t *reg) { char *caller = (char*)(*(uint16_t*)®->trapret + ( reg->mbase << 16)); char dir = caller[1]; char c = reg->af >> 8; if(dir) // input switch((port_CONIO_t) caller[2]) { case CONSTA: // console status port if(xQueuePeek(cpminq,&c,0) == pdTRUE) reg->af |= 0xFF00; else reg->af &= ~0xFF00; break; case CONDAT: // console data port if(xQueueReceive(cpminq,&c,portMAX_DELAY) == pdTRUE) reg->af = reg->af & ~0xFF00 | (c << 8); else reg->af &= ~0xFF00; break; case PRTSTA: // printer status port case PRTDAT: // printer data port case AUXDAT: // auxiliary data port default: reg->af &= ~0xFF00; break; } else // output switch((port_CONIO_t) caller[2]) { case CONDAT: // console data port FreeRTOS_send(xConnectedSocket,&c,1,0); break; case CONSTA: // console status port case PRTSTA: // printer status port case PRTDAT: // printer data port case AUXDAT: // auxiliary data port default: break; }; }
void prvTCPCpmIOTask( void *ram ) { BaseType_t iosize; char cRxedChar, cInputIndex = 0; struct freertos_sockaddr xClient; Socket_t xListeningSocket; socklen_t xSize = sizeof( xClient ); cpminq = xQueueCreate(81, sizeof( CHAR)); while(FreeRTOS_IsNetworkUp() == pdFALSE) vTaskDelay(3000); /* Create the socket. */ xSocketRDisk = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); /* Check the socket was created. */ configASSERT( xSocketRDisk != FREERTOS_INVALID_SOCKET ); for( ;; ) { /* Attempt to open the socket. The port number is passed in the task parameter. The strange casting is to remove compiler warnings on 32-bit machines. NOTE: The FREERTOS_SO_REUSE_LISTEN_SOCKET option is used, so the listening and connecting socket are the same - meaning only one connection will be accepted at a time, and that xListeningSocket must be created on each iteration. */ xListeningSocket = prvOpenTCPServerSocket( RDSK_PORT); /* Nothing for this task to do if the socket cannot be created. */ if( xListeningSocket == FREERTOS_INVALID_SOCKET ) { vTaskDelete( NULL ); } /* Wait for an incoming connection. */ xConnectedSocket = FreeRTOS_accept( xListeningSocket, &xClient, &xSize ); /* The FREERTOS_SO_REUSE_LISTEN_SOCKET option is set, so the connected and listening socket should be the same socket. */ configASSERT( xConnectedSocket == xListeningSocket ); xRDiskAddress.sin_addr = xClient.sin_addr; xRDiskAddress.sin_port = FreeRTOS_htons( RDSK_PORT ); iosize = xTaskCreate( CPM22Task, "CPM22Task", configMINIMAL_STACK_SIZE*5, ram, PRIO_CPM22,&thcpm); if(iosize != pdPASS) { prvGracefulShutdown( xListeningSocket ); vTaskDelete( NULL ); } /* Send the welcome message. */ iosize = FreeRTOS_send( xConnectedSocket, ( void * ) pcWelcomeMessage, strlen( pcWelcomeMessage ), 0 ); xQueueReset(cpminq); /* Process the socket as long as it remains connected. */ while( iosize >= 0 ) { char c; /* Receive data on the socket. */ iosize = FreeRTOS_recv( xConnectedSocket, &c, 1, 0 ); if( iosize >= 0 ) { xQueueSend(cpminq,&c,0); } else { /* Socket closed? */ break; } } /* Close the socket correctly. */ prvGracefulShutdown( xListeningSocket ); } }
static void prvServerConnectionInstance( void *pvParameters ) { int32_t lBytes, lSent, lTotalSent; uint8_t cReceivedString[ ipconfigTCP_MSS ]; xSocket_t xConnectedSocket; static const TickType_t xReceiveTimeOut = pdMS_TO_TICKS( 5000 ); static const TickType_t xSendTimeOut = pdMS_TO_TICKS( 5000 ); TickType_t xTimeOnShutdown; ulConnectionCount++; xConnectedSocket = ( xSocket_t ) pvParameters; FreeRTOS_setsockopt( xConnectedSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) ); FreeRTOS_setsockopt( xConnectedSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendTimeOut, sizeof( xReceiveTimeOut ) ); for( ;; ) { /* Zero out the receive array so there is NULL at the end of the string when it is printed out. */ memset( cReceivedString, 0x00, sizeof( cReceivedString ) ); /* Receive data on the socket. */ lBytes = FreeRTOS_recv( xConnectedSocket, cReceivedString, sizeof( cReceivedString ), 0 ); /* If data was received, echo it back. */ if( lBytes >= 0 ) { lSent = 0; lTotalSent = 0; /* Call send() until all the data has been sent. */ while( ( lSent >= 0 ) && ( lTotalSent < lBytes ) ) { lSent = FreeRTOS_send( xConnectedSocket, cReceivedString, lBytes - lTotalSent, 0 ); lTotalSent += lSent; } if( lSent < 0 ) { /* Socket closed? */ break; } } else { /* Socket closed? */ break; } } /* Initiate a shutdown in case it has not already been initiated. */ FreeRTOS_shutdown( xConnectedSocket, FREERTOS_SHUT_RDWR ); /* Wait for the shutdown to take effect, indicated by FreeRTOS_recv() returning an error. */ xTimeOnShutdown = xTaskGetTickCount(); do { if( FreeRTOS_recv( xConnectedSocket, cReceivedString, ipconfigTCP_MSS, 0 ) < 0 ) { break; } } while( ( xTaskGetTickCount() - xTimeOnShutdown ) < tcpechoSHUTDOWN_DELAY ); /* Finished with the socket and the task. */ FreeRTOS_closesocket( xConnectedSocket ); vTaskDelete( NULL ); }
static BaseType_t prvSendFile( xHTTPClient *pxClient ) { size_t xSpace; size_t xCount; BaseType_t xRc = 0; if( pxClient->bits.bReplySent == pdFALSE ) { pxClient->bits.bReplySent = pdTRUE; strcpy( pxClient->pxParent->pcContentsType, pcGetContentsType( pxClient->pcCurrentFilename ) ); snprintf( pxClient->pxParent->pcExtraContents, sizeof pxClient->pxParent->pcExtraContents, "Content-Length: %d\r\n", ( int ) pxClient->xBytesLeft); xRc = prvSendReply( pxClient, WEB_REPLY_OK ); /* "Requested file action OK" */ } if( xRc >= 0 ) do { xSpace = FreeRTOS_tx_space( pxClient->xSocket ); if( pxClient->xBytesLeft < xSpace ) { xCount = pxClient->xBytesLeft; } else { xCount = xSpace; } if( xCount > 0 ) { if( xCount > sizeof( pxClient->pxParent->pcFileBuffer ) ) { xCount = sizeof( pxClient->pxParent->pcFileBuffer ); } ff_fread( pxClient->pxParent->pcFileBuffer, 1, xCount, pxClient->pxFileHandle ); pxClient->xBytesLeft -= xCount; xRc = FreeRTOS_send( pxClient->xSocket, pxClient->pxParent->pcFileBuffer, xCount, 0 ); if( xRc < 0 ) { break; } } } while( xCount > 0 ); if( pxClient->xBytesLeft <= 0 ) { /* Writing is ready, no need for further 'eSELECT_WRITE' events. */ FreeRTOS_FD_CLR( pxClient->xSocket, pxClient->pxParent->xSocketSet, eSELECT_WRITE ); prvFileClose( pxClient ); } else { /* Wake up the TCP task as soon as this socket may be written to. */ FreeRTOS_FD_SET( pxClient->xSocket, pxClient->pxParent->xSocketSet, eSELECT_WRITE ); } return xRc; }
static void prvEchoClientTask( void *pvParameters ) { Socket_t xSocket; struct freertos_sockaddr xEchoServerAddress; int32_t lLoopCount = 0UL; const int32_t lMaxLoopCount = 1; volatile uint32_t ulTxCount = 0UL; BaseType_t xReceivedBytes, xReturned, xInstance; BaseType_t lTransmitted, lStringLength; char *pcTransmittedString, *pcReceivedString; WinProperties_t xWinProps; TickType_t xTimeOnEntering; /* Fill in the buffer and window sizes that will be used by the socket. */ xWinProps.lTxBufSize = 6 * ipconfigTCP_MSS; xWinProps.lTxWinSize = 3; xWinProps.lRxBufSize = 6 * ipconfigTCP_MSS; xWinProps.lRxWinSize = 3; /* This task can be created a number of times. Each instance is numbered to enable each instance to use a different Rx and Tx buffer. The number is passed in as the task's parameter. */ xInstance = ( BaseType_t ) pvParameters; /* Point to the buffers to be used by this instance of this task. */ pcTransmittedString = &( cTxBuffers[ xInstance ][ 0 ] ); pcReceivedString = &( cRxBuffers[ xInstance ][ 0 ] ); /* Echo requests are sent to the echo server. The address of the echo server is configured by the constants configECHO_SERVER_ADDR0 to configECHO_SERVER_ADDR3 in FreeRTOSConfig.h. */ xEchoServerAddress.sin_port = FreeRTOS_htons( echoECHO_PORT ); xEchoServerAddress.sin_addr = FreeRTOS_inet_addr_quick( configECHO_SERVER_ADDR0, configECHO_SERVER_ADDR1, configECHO_SERVER_ADDR2, configECHO_SERVER_ADDR3 ); for( ;; ) { /* Create a TCP socket. */ xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP ); configASSERT( xSocket != FREERTOS_INVALID_SOCKET ); /* Set a time out so a missing reply does not cause the task to block indefinitely. */ FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) ); FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendTimeOut, sizeof( xSendTimeOut ) ); /* Set the window and buffer sizes. */ FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &xWinProps, sizeof( xWinProps ) ); /* Connect to the echo server. */ if( FreeRTOS_connect( xSocket, &xEchoServerAddress, sizeof( xEchoServerAddress ) ) == 0 ) { ulConnections[ xInstance ]++; /* Send a number of echo requests. */ for( lLoopCount = 0; lLoopCount < lMaxLoopCount; lLoopCount++ ) { /* Create the string that is sent to the echo server. */ lStringLength = prvCreateTxData( pcTransmittedString, echoBUFFER_SIZES ); /* Add in some unique text at the front of the string. */ sprintf( pcTransmittedString, "TxRx message number %u", ulTxCount ); ulTxCount++; /* Send the string to the socket. */ lTransmitted = FreeRTOS_send( xSocket, /* The socket being sent to. */ ( void * ) pcTransmittedString, /* The data being sent. */ lStringLength, /* The length of the data being sent. */ 0 ); /* No flags. */ if( lTransmitted < 0 ) { /* Error? */ break; } /* Clear the buffer into which the echoed string will be placed. */ memset( ( void * ) pcReceivedString, 0x00, echoBUFFER_SIZES ); xReceivedBytes = 0; /* Receive data echoed back to the socket. */ while( xReceivedBytes < lTransmitted ) { xReturned = FreeRTOS_recv( xSocket, /* The socket being received from. */ &( pcReceivedString[ xReceivedBytes ] ),/* The buffer into which the received data will be written. */ lStringLength - xReceivedBytes, /* The size of the buffer provided to receive the data. */ 0 ); /* No flags. */ if( xReturned < 0 ) { /* Error occurred. Latch it so it can be detected below. */ xReceivedBytes = xReturned; break; } else if( xReturned == 0 ) { /* Timed out. */ break; } else { /* Keep a count of the bytes received so far. */ xReceivedBytes += xReturned; } } /* If an error occurred it will be latched in xReceivedBytes, otherwise xReceived bytes will be just that - the number of bytes received from the echo server. */ if( xReceivedBytes > 0 ) { /* Compare the transmitted string to the received string. */ configASSERT( strncmp( pcReceivedString, pcTransmittedString, lTransmitted ) == 0 ); if( strncmp( pcReceivedString, pcTransmittedString, lTransmitted ) == 0 ) { /* The echo reply was received without error. */ ulTxRxCycles[ xInstance ]++; } else { /* The received string did not match the transmitted string. */ ulTxRxFailures[ xInstance ]++; break; } } else if( xReceivedBytes < 0 ) { /* FreeRTOS_recv() returned an error. */ break; } else { /* Timed out without receiving anything? */ break; } } /* Finished using the connected socket, initiate a graceful close: FIN, FIN+ACK, ACK. */ FreeRTOS_shutdown( xSocket, FREERTOS_SHUT_RDWR ); /* Expect FreeRTOS_recv() to return an error once the shutdown is complete. */ xTimeOnEntering = xTaskGetTickCount(); do { xReturned = FreeRTOS_recv( xSocket, /* The socket being received from. */ &( pcReceivedString[ 0 ] ), /* The buffer into which the received data will be written. */ echoBUFFER_SIZES, /* The size of the buffer provided to receive the data. */ 0 ); if( xReturned < 0 ) { break; } } while( ( xTaskGetTickCount() - xTimeOnEntering ) < xReceiveTimeOut ); } /* Close this socket before looping back to create another. */ FreeRTOS_closesocket( xSocket ); /* Pause for a short while to ensure the network is not too congested. */ vTaskDelay( echoLOOP_DELAY ); } }
static BaseType_t prvOpenURL( HTTPClient_t *pxClient ) { BaseType_t xRc; char pcSlash[ 2 ]; pxClient->bits.ulFlags = 0; #if( ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK != 0 ) { if( strchr( pxClient->pcUrlData, ipconfigHTTP_REQUEST_CHARACTER ) != NULL ) { size_t xResult; xResult = uxApplicationHTTPHandleRequestHook( pxClient->pcUrlData, pxClient->pcCurrentFilename, sizeof( pxClient->pcCurrentFilename ) ); if( xResult > 0 ) { strcpy( pxClient->pxParent->pcContentsType, "text/html" ); snprintf( pxClient->pxParent->pcExtraContents, sizeof( pxClient->pxParent->pcExtraContents ), "Content-Length: %d\r\n", ( int ) xResult ); xRc = prvSendReply( pxClient, WEB_REPLY_OK ); /* "Requested file action OK" */ if( xRc > 0 ) { xRc = FreeRTOS_send( pxClient->xSocket, pxClient->pcCurrentFilename, xResult, 0 ); } /* Although against the coding standard of FreeRTOS, a return is done here to simplify this conditional code. */ return xRc; } } } #endif /* ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK */ if( pxClient->pcUrlData[ 0 ] != '/' ) { /* Insert a slash before the file name. */ pcSlash[ 0 ] = '/'; pcSlash[ 1 ] = '\0'; } else { /* The browser provided a starting '/' already. */ pcSlash[ 0 ] = '\0'; } snprintf( pxClient->pcCurrentFilename, sizeof( pxClient->pcCurrentFilename ), "%s%s%s", pxClient->pcRootDir, pcSlash, pxClient->pcUrlData); pxClient->pxFileHandle = ff_fopen( pxClient->pcCurrentFilename, "rb" ); FreeRTOS_printf( ( "Open file '%s': %s\n", pxClient->pcCurrentFilename, pxClient->pxFileHandle != NULL ? "Ok" : strerror( stdioGET_ERRNO() ) ) ); if( pxClient->pxFileHandle == NULL ) { /* "404 File not found". */ xRc = prvSendReply( pxClient, WEB_NOT_FOUND ); } else { pxClient->uxBytesLeft = ( size_t ) pxClient->pxFileHandle->ulFileSize; xRc = prvSendFile( pxClient ); } return xRc; }