Forum Post: RE: 4GL Sockets and Hexadecimal values...

  • Thread starter Thread starter MBeynon
  • Start date Start date
Status
Not open for further replies.
M

MBeynon

Guest
Matt, First of all, thanks for taking an ineterest in this :-) "Or does the API expect a 4-byte value?" That's the problem. The API expects a 4 byte value whereas I can only currently supply 8 (INT64). Here's SocketConnect in its entirety followed by en excerpt from the API I'm trying to conform to: PROCEDURE SocketConnect : /*------------------------------------------------------------------------------ Purpose: Handle the response from the remote server Parameters: none Notes: ------------------------------------------------------------------------------*/ DEFINE INPUT PARAMETER ipcHost AS CHARACTER NO-UNDO. DEFINE INPUT PARAMETER ipiPort AS INTEGER NO-UNDO. DEFINE INPUT PARAMETER ipcProtocol AS CHARACTER NO-UNDO. DEFINE INPUT PARAMETER ipiTimeout AS INTEGER NO-UNDO. DEFINE INPUT PARAMETER ipcUserName AS CHARACTER NO-UNDO. DEFINE INPUT PARAMETER lvi64Header AS INT64 NO-UNDO. DEFINE INPUT PARAMETER ipcPassWord AS CHARACTER NO-UNDO. DEFINE OUTPUT PARAMETER oplErrorMsg AS LOGICAL NO-UNDO. DEFINE VARIABLE lvmMEMPTRHeader AS MEMPTR NO-UNDO. ASSIGN SET-SIZE(lvmMEMPTRHeader) = 8 SET-BYTE-ORDER(lvmMEMPTRHeader) = LITTLE-ENDIAN PUT-UNSIGNED-LONG(lvmMEMPTRHeader,1) = lvi64Header. DEFINE VARIABLE lvmMEMPTRDataSize AS MEMPTR NO-UNDO. ASSIGN SET-SIZE(lvmMEMPTRDataSize) = 2 SET-BYTE-ORDER(lvmMEMPTRDataSize) = LITTLE-ENDIAN PUT-UNSIGNED-SHORT (lvmMEMPTRDataSize,1) = (LENGTH(ipcUserName) + 1) + LENGTH(ipcPassWord) + 1. _process: DO: DO ON ERROR UNDO, LEAVE: /* Open a socket connection to the server */ CREATE SOCKET lvhSocket. lvlStatus = lvhSocket:SET-READ-RESPONSE-PROCEDURE("ReadHandler":U, THIS-PROCEDURE) NO-ERROR. IF NOT lvlStatus THEN DO: ASSIGN opiResultCode = {&ERR_CONNECT_FAILURE} opcResultDesc = "Unable to set readresponse : " + ERROR-STATUS:GET-MESSAGE(1). LEAVE _process. END. ASSIGN lvlStatus = lvhSocket:CONNECT(SUBSTITUTE("-H &1 -S &2 &3 &4":U, ipcHost, ipiPort, IF ipcProtocol = {&PROTOCOL_HTTPS} OR ipcProtocol = {&PROTOCOL_HTTPS_UNVERIFIED} THEN "-ssl":U ELSE "":U, IF ipcProtocol = {&PROTOCOL_HTTPS_UNVERIFIED} THEN "-nohostverify":U ELSE "":U )) NO-ERROR. /* Now make sure the socket is open */ IF lvlStatus = NO OR NOT lvhSocket:CONNECTED() THEN DO: ASSIGN opiResultCode = {&ERR_CONNECT_FAILURE} opcResultDesc = "Unable to connect to socket : " + ERROR-STATUS:GET-MESSAGE(1). LEAVE _process. END. /* Set the timeout on the socket receive wait lvhSocket:SET-SOCKET-OPTION("SO-RCVTIMEO", STRING(ipiTimeout)).*/ /* Got a socket connection - now make the request */ ASSIGN SET-SIZE (lvhBuffer) = 8 + 2 + 8186 PUT-BYTES (lvhBuffer,1) = lvmMEMPTRHeader PUT-BYTES (lvhBuffer,9) = lvmMEMPTRDataSize PUT-STRING (lvhBuffer,11) = ipcUserName + "0" PUT-STRING (lvhBuffer,23) = ipcPassWord + "0". ASSIGN lvlStatus = lvhSocket:WRITE(lvhBuffer, 1, LENGTH(lvcRequestString)) NO-ERROR. IF NOT lvlStatus OR ERROR-STATUS:ERROR THEN DO: ASSIGN opiResultCode = {&ERR_TRANSMIT_FAILURE} opcResultDesc = "Unable to transmit to socket : " + ERROR-STATUS:GET-MESSAGE(1). LEAVE _process. END. /* Wait for a response */ ASSIGN lvlWaitingForResponse = TRUE /* Turned off when request is done */ lviStart = ETIME. WAIT-FOR READ-RESPONSE OF lvhSocket. END. LEAVE _process. END. /* _process */ ASSIGN oplErrorMsg = opcResultDesc "":U. FINALLY: /* Cleanup our resources */ SET-SIZE(lvhBuffer) = 0. SET-SIZE(lvmMEMPTRHeader) = 0. SET-SIZE(lvmMEMPTRDataSize) = 0. lvhSocket:DISCONNECT(). DELETE OBJECT lvhSocket NO-ERROR. END FINALLY. END PROCEDURE. API: All data sent over this interface must use 1 byte structure member alignment. All multi-byte numeric values are to use little-endian byte ordering. A command is structured thus: ULONG ulCommand // Command code (CSI_xx) USHORT usLength // Length of data to follow (can be zero) DATA data // data for the command (max. 8186 bytes) Message identifiers are unsigned 32-bit values (ULONG). This value is coded so as to allow simple decomposition of the messaging domain. The coding operates as follows starting with the most significant bit and working towards the least significant bit as in the table on the following page: Number of bits Purpose 4 Message type (t): 1000 = Command 1001 = Response 1002 = Event Other values reserved for future expansion 12 Functional area (f): 100000000000 = General 100000000001 = Configuration 100000000010 = Archiving 100000000011 = Search 100000000100 = Replay 100000000101 = Statistics 100000000110 = Engineer Other values reserved for future expansion 16 Specific message identifier (s) - these are to be defined as necessary. This method will not necessarily be as human readable as a system oriented around standard decimal partitioning but as hexadecimal (0xtfffssss) it is still human readable and easily manipulated from a programming point of view. Message identifiers are constructed from the three component parts. For example: #define CSI 0x80000000 #define RSI 0x90000000 #define ESI 0xA0000000 #define SIF_GENERAL 0x08000000 #define SIF_CONFIGURATION 0x08010000 #define SIF_ARCHIVE 0x08020000 #define SIF_SEARCH 0x08030000 #define SIF_REPLAY 0x08040000 #define SIF_STATISTICS 0x08050000 #define SIF_ENGINEER 0x08060000 #define SIS_UNKNOWN_COMMAND 0x00000000 #define SIS_BAD_DATA 0x00000001 Thanks, Mark.

Continue reading...
 
Status
Not open for further replies.
Back
Top