You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

207 lines
6.3 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2014 Jean-Pierre Charras, jp.charras at wanadoo.fr
  5. * Copyright (C) 2014 KiCad Developers, see CHANGELOG.TXT for contributors.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, you may find one here:
  19. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  20. * or you may search the http://www.gnu.org website for the version 2 license,
  21. * or you may write to the Free Software Foundation, Inc.,
  22. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  23. */
  24. /**
  25. * @file eda_dde.cpp
  26. */
  27. #include <fctsys.h>
  28. #include <eda_dde.h>
  29. #include <eda_draw_frame.h>
  30. #include <id.h>
  31. #include <common.h>
  32. #include <macros.h>
  33. static const wxString HOSTNAME( wxT( "localhost" ) );
  34. // buffer for read and write data in socket connections
  35. #define IPC_BUF_SIZE 4096
  36. static char client_ipc_buffer[IPC_BUF_SIZE];
  37. /**********************************/
  38. /* Routines related to the server */
  39. /**********************************/
  40. /* Function to initialize a server socket
  41. */
  42. void EDA_DRAW_FRAME::CreateServer( int service, bool local )
  43. {
  44. wxIPV4address addr;
  45. // Set the port number
  46. addr.Service( service );
  47. // Listen on localhost only if requested
  48. if( local )
  49. addr.Hostname( HOSTNAME );
  50. delete m_socketServer;
  51. m_socketServer = new wxSocketServer( addr );
  52. m_socketServer->SetNotify( wxSOCKET_CONNECTION_FLAG );
  53. m_socketServer->SetEventHandler( *this, ID_EDA_SOCKET_EVENT_SERV );
  54. m_socketServer->Notify( true );
  55. }
  56. /* Function called on every client request.
  57. */
  58. void EDA_DRAW_FRAME::OnSockRequest( wxSocketEvent& evt )
  59. {
  60. size_t len;
  61. wxSocketBase* sock = evt.GetSocket();
  62. switch( evt.GetSocketEvent() )
  63. {
  64. case wxSOCKET_INPUT:
  65. sock->Read( client_ipc_buffer, 1 );
  66. if( sock->LastCount() == 0 )
  67. break; // No data, occurs on opening connection
  68. sock->Read( client_ipc_buffer + 1, IPC_BUF_SIZE - 2 );
  69. len = 1 + sock->LastCount();
  70. client_ipc_buffer[len] = 0;
  71. ExecuteRemoteCommand( client_ipc_buffer );
  72. break;
  73. case wxSOCKET_LOST:
  74. return;
  75. break;
  76. default:
  77. wxPrintf( wxT( "EDA_DRAW_FRAME::OnSockRequest() error: Invalid event !" ) );
  78. break;
  79. }
  80. }
  81. /* Function called when a connection is requested by a client.
  82. */
  83. void EDA_DRAW_FRAME::OnSockRequestServer( wxSocketEvent& evt )
  84. {
  85. wxSocketBase* socket;
  86. wxSocketServer* server = (wxSocketServer*) evt.GetSocket();
  87. socket = server->Accept();
  88. if( socket == NULL )
  89. return;
  90. m_sockets.push_back( socket );
  91. socket->Notify( true );
  92. socket->SetEventHandler( *this, ID_EDA_SOCKET_EVENT );
  93. socket->SetNotify( wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG );
  94. }
  95. /**********************************/
  96. /* Routines related to the CLIENT */
  97. /**********************************/
  98. /* Used by a client to sent (by a socket connection) a data to a server.
  99. * - Open a Socket Client connection
  100. * - Send the buffer cmdline
  101. * - Close the socket connection
  102. *
  103. * service is the service number for the TC/IP connection
  104. */
  105. bool SendCommand( int service, const char* cmdline )
  106. {
  107. wxSocketClient* sock_client;
  108. bool success = false;
  109. wxIPV4address addr;
  110. // Create a connexion
  111. addr.Hostname( HOSTNAME );
  112. addr.Service( service );
  113. // Mini-tutorial for Connect() :-)
  114. // (JP CHARRAS Note: see wxWidgets: sockets/client.cpp sample)
  115. // ---------------------------
  116. //
  117. // There are two ways to use Connect(): blocking and non-blocking,
  118. // depending on the value passed as the 'wait' (2nd) parameter.
  119. //
  120. // Connect(addr, true) will wait until the connection completes,
  121. // returning true on success and false on failure. This call blocks
  122. // the GUI (this might be changed in future releases to honor the
  123. // wxSOCKET_BLOCK flag).
  124. //
  125. // Connect(addr, false) will issue a nonblocking connection request
  126. // and return immediately. If the return value is true, then the
  127. // connection has been already successfully established. If it is
  128. // false, you must wait for the request to complete, either with
  129. // WaitOnConnect() or by watching wxSOCKET_CONNECTION / LOST
  130. // events (please read the documentation).
  131. //
  132. // WaitOnConnect() itself never blocks the GUI (this might change
  133. // in the future to honor the wxSOCKET_BLOCK flag). This call will
  134. // return false on timeout, or true if the connection request
  135. // completes, which in turn might mean:
  136. //
  137. // a) That the connection was successfully established
  138. // b) That the connection request failed (for example, because
  139. // it was refused by the peer.
  140. //
  141. // Use IsConnected() to distinguish between these two.
  142. //
  143. // So, in a brief, you should do one of the following things:
  144. //
  145. // For blocking Connect:
  146. //
  147. // bool success = client->Connect(addr, true);
  148. //
  149. // For nonblocking Connect:
  150. //
  151. // client->Connect(addr, false);
  152. //
  153. // bool waitmore = true;
  154. // while (! client->WaitOnConnect(seconds, millis) && waitmore )
  155. // {
  156. // // possibly give some feedback to the user,
  157. // // update waitmore if needed.
  158. // }
  159. // bool success = client->IsConnected();
  160. //
  161. // And that's all :-)
  162. sock_client = new wxSocketClient();
  163. sock_client->SetTimeout( 2 ); // Time out in Seconds
  164. sock_client->Connect( addr, false );
  165. sock_client->WaitOnConnect( 0, 100 );
  166. if( sock_client->Ok() && sock_client->IsConnected() )
  167. {
  168. success = true;
  169. sock_client->SetFlags( wxSOCKET_NOWAIT /*wxSOCKET_WAITALL*/ );
  170. sock_client->Write( cmdline, strlen( cmdline ) );
  171. }
  172. sock_client->Close();
  173. sock_client->Destroy();
  174. return success;
  175. }