1 /***********************************************************************/ 2 /* Open Visualization Data Explorer */ 3 /* (C) Copyright IBM Corp. 1989,1999 */ 4 /* ALL RIGHTS RESERVED */ 5 /* This code licensed under the */ 6 /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */ 7 /***********************************************************************/ 8 9 #include <dxconfig.h> 10 #include "../base/defines.h" 11 12 13 14 15 #ifndef _PacketIF_h 16 #define _PacketIF_h 17 18 #include <stdio.h> 19 #include <X11/Intrinsic.h> 20 21 #include "Base.h" 22 #include "PacketHandler.h" 23 #include "LinkHandler.h" 24 #include "List.h" 25 #include "QueuedPackets.h" 26 27 #if defined(intelnt) && defined(ERROR) 28 #undef ERROR 29 #endif 30 31 32 // 33 // Class name definition: 34 // 35 #define ClassPacketIF "PacketIF" 36 37 // 38 // XtCallbackProc (*CB), XtEventHandler (*EH) and XtActionProc (*AP) 39 // DialogCallback (*DCB), XtInputCallbackProc (*ICP), XtWorkProc (*WP) 40 // functions for this and derived classes 41 // 42 extern "C" void PacketIF_InputIdleTimerTCP(XtPointer, XtIntervalId*); 43 extern "C" Boolean PacketIF_InputIdleWP(XtPointer); 44 extern "C" Boolean PacketIF_QueuedPacketWP(XtPointer); 45 extern "C" void PacketIF_ProcessSocketInputICB(XtPointer, int*, XtInputId*); 46 47 #if defined(DXD_IBM_OS2_SOCKETS) || defined(DXD_HAS_WINSOCKETS) 48 int UxSend(int s, const char *ExternalBuffer, int TotalBytesToSend, int Flags); 49 int UxRecv(int s, char *ExternalBuffer, int BuffSize, int Flags); 50 #endif 51 52 53 typedef void (*PacketIFCallback)(void *clientData, char *echoString); 54 typedef boolean (*StallingHandler)(void *clientData); 55 56 // 57 // PacketIF class definition: 58 // 59 class PacketIF : public Base 60 { 61 62 // 63 // Allow the LinkHandlers to send packets. 64 // 65 friend void LinkHandler::sendPacket(int , int , const char *, int); 66 friend void QueuedPacket::send(PacketIF*); 67 friend void QueuedBytes::send(PacketIF*); 68 friend void QueuedImmediate::send(PacketIF*); 69 70 private: 71 // 72 // Private member data: 73 // 74 75 // 76 // I hate this... on some AIX systems, it seems that the work proc can 77 // get called even after the PacketIF deletion method is called. When this 78 // happens, the work proc receives a deleted PacketIF, and all hell breaks 79 // loose. Instead, I'm going to use double indirection... I'll allocate a 80 // pointer when the PacketIF is created, set it to point to the PacketIF 81 // itselfkeep a pointer to it in the PacketIF, and pass its address as the 82 // work proc client data. When the PacketIF is deleted, the pointer is set 83 // to NULL, but not freed. So if the pointer that the work proc receives as 84 // its client data points to NULL, we know that the PacketIF has been deleted 85 // and the work proc returns immediately. Unfortunately, this leaks space 86 // for a pointer for each packetIF created. 87 // 88 PacketIF **wpClientData; 89 90 int error; 91 int socket; 92 FILE *stream; 93 XtInputId inputHandlerId; 94 boolean deferPacketHandling; 95 XtWorkProcId workProcId; 96 XtIntervalId workProcTimerId; 97 int line_length; 98 int alloc_line_length; 99 100 friend void PacketIF_InputIdleTimerTCP(XtPointer, XtIntervalId*); 101 friend Boolean PacketIF_InputIdleWP(XtPointer clientData); 102 friend Boolean PacketIF_QueuedPacketWP(XtPointer clientData); 103 friend void PacketIF_ProcessSocketInputICB(XtPointer clientData, 104 int *socket, 105 XtInputId *id); 106 PacketIFCallback echoCallback; 107 void *echoClientData; 108 109 PacketIFCallback errorCallback; 110 void *errorClientData; 111 112 boolean endReceiving; 113 void *endReceiveData; // Data passed back by 114 115 StallingHandler stallingWorker; 116 void *stallingWorkerData; 117 118 /* 119 * Open a socket port and wait for a client to connect. 120 * This opens 2 sockets (except on the server), one internet domain, and 121 * one unix domain. It then selects on both sockets to see to which one the 122 * app connects, and returns the new connection, closing the one not 123 * selected. 124 */ 125 void connectAsServer(int pport); 126 127 void connectAsClient(const char *host, int port, boolean local); 128 129 // 130 // Control whether or not the callbacks to handle messages on the 131 // wire will be called. 132 // 133 void installInputHandler(); 134 void removeInputHandler(); 135 136 // 137 // These methods are used to make the handling of packets a lower 138 // priority than the events coming from the display. Basically, 139 // we don't enable the handling of a message until the WorkProc 140 // is called (indicating that there are no other events to handle). 141 // 142 void installWorkProc(); 143 void removeWorkProc(); 144 void installWorkProcTimer(); 145 void removeWorkProcTimer(); 146 147 148 protected: 149 // 150 // Protected member data: 151 // 152 153 List handlers; // List of PacketHandler's. 154 155 virtual void parsePacket(); 156 char *line; 157 158 159 // 160 // Handle stream read/write errors. We handle SIGPIPE/EPIPE specially. 161 // SIGPIPE is ignored and then if we get an EPIPE on a write, then we 162 // know the server or other connect has gone away. 163 // The errnum is passed in for portability, but is ignored on UNIX 164 // systems. 165 // 166 void handleStreamError(int errnum, const char *msg); 167 168 // 169 // Receive a packet. 170 // If readSocket is FALSE, then we just process packets that are still 171 // in the line buffer. 172 // 173 void packetReceive(boolean readSocket = TRUE); 174 175 // 176 // Routines to handle PacketIF messages. 177 // 178 static void ProcessMessage(void *clientData, int id, void *line); 179 static void ProcessInformation(void *clientData, int id, void *line); 180 static void ProcessError(void *clientData, int id, void *line); 181 static void ProcessErrorWARNING(void *clientData, int id, void *line); 182 static void ProcessErrorERROR(void *clientData, int id, void *p); 183 static void ProcessCompletion(void *clientData, int id, void *line); 184 static void ProcessInterrupt(void *clientData, int id, void *line); 185 static void ProcessBeginExecNode(void *clientData, int id, void *line); 186 static void ProcessEndExecNode(void *clientData, int id, void *line); 187 static void ProcessLinkCommand(void *clientData, int id, void *p); 188 static void HandleError(void *clientData, char *message); 189 190 LinkHandler *linkHandler; 191 virtual void installLinkHandler(); 192 193 // 194 // Queue outgoing messages in order to avoid deadlock with dxexec 195 // 196 void _sendBytes(const char *string); 197 void _sendImmediate(const char *string); 198 void _sendPacket(int type, int packetId, const char *data = NULL, int length = 0); 199 Boolean sendQueuedPackets(); 200 boolean isSocketInputReady(); 201 List output_queue; 202 int output_queue_wpid; 203 void sendPacket(int type, int packetId, const char *data = NULL, int length = 0); 204 205 public: 206 207 static const char* PacketTypes[]; 208 209 enum { 210 INTERRUPT = 1, 211 SYSTEM = 2, 212 ACK = 3, 213 MACRODEF = 4, 214 FOREGROUND = 5, 215 BACKGROUND = 6, 216 PKTERROR = 7, 217 MESSAGE = 8, 218 INFORMATION = 9, 219 LINQUIRY = 10, 220 LRESPONSE = 11, 221 LDATA = 12, 222 SINQUIRY = 13, 223 SRESPONSE = 14, 224 SDATA = 15, 225 VINQUIRY = 16, 226 VRESPONSE = 17, 227 VDATA = 18, 228 COMPLETE = 19, 229 IMPORT = 20, 230 IMPORTINFO = 21, 231 LINK = 22 232 }; 233 234 // 235 // Constructor: 236 // 237 PacketIF(const char *server, int port, boolean local, boolean asClient); 238 239 // 240 // Destructor: 241 // 242 ~PacketIF(); 243 244 // 245 // Initializer 246 // 247 virtual void initializePacketIO(); 248 inError()249 int inError() {return this->error;} 250 251 void setHandler(int type, 252 PacketHandlerCallback callback, 253 void *clientData, 254 const char *matchString = NULL); 255 256 // 257 // Error and echo handling callbacks. Echos are not performed if no 258 // callback has been set up. Errors are dumped to stderr if nothing 259 // has been set up. 260 // 261 void setErrorCallback(PacketIFCallback callback, void *clientData); 262 PacketIFCallback getErrorCallback(void **clientData = NULL); 263 void setEchoCallback(PacketIFCallback callback, void *clientData); 264 PacketIFCallback getEchoCallback(void **clientData = NULL); 265 266 void sendBytes(const char *string); 267 void sendImmediate(const char *string); 268 269 // 270 // Return TRUE if there was NOT a packet error. 271 // If returning TRUE and data!=NULL, then *data is set to the value 272 // passed to the endReceiveContinuous() call. 273 // 274 boolean receiveContinuous(void **data = NULL); 275 276 // 277 // Terminates receiveContinuous() and causes it to set its *data to 278 // the data value passed in. 279 // 280 void endReceiveContinuous(void *data = NULL); 281 282 // 283 // This is the file descriptor. It may ONLY be used to write a 284 // network to the executive between sendMacroStart and sendMacroEnd. 285 // Anything written to this FILE must be also sent to the routine 286 // accessed via "getEchoCallback". getFILE()287 FILE *getFILE() { return this->stream; } 288 289 290 void executeLinkCommand(const char *c, int id); 291 292 // 293 // Defer handing of messages until the function h is called (periodically) 294 // and returns TRUE. At that point handling is reenabled. 295 // If stalling was not already enabled and there are no other problems, 296 // then we return TRUE, otherwise FALSE. 297 // Use isPacketHandlingStalled() to determine if handling is currently 298 // stalled. 299 // 300 boolean stallPacketHandling(StallingHandler h, void *data); 301 boolean isPacketHandlingStalled(); 302 303 // 304 // Returns a pointer to the class name. 305 // getClassName()306 const char* getClassName() 307 { 308 return ClassPacketIF; 309 } 310 }; 311 #endif // _PacketIF_h 312