Sidebar

plugins:07_keyedconstants

Plugin API: Listening For Incoming Connections and Making Outgoing Connections

In XTension version 9.3.3 the API version was updated to version 2 and support for listening or incoming connections was added. This is currently incomplete documentation as that version hasn’t been released yet. Stay tuned for more info.

Server Commands

XTStartTCPListener

The XTStartTCPListener command will startup a listening server on the requested port for the requested protocol. The function will return an ID number if the startup was successful or 0 if the port was in use or other error occurred. You should save the returned ID in order to stop the server listening later. The same automatic boundary parsing that can be applied to interface started connections can be applied to this. The connection events and data available events are described below in the Server Events section.

myServer = XTStartTCPListener( thePort, theBoundryString)
if myServer == 0:
  XTWriteLog( “an error occurred trying to bind a new listener to port “ + str( thePort))

XTStopTCPListener

Pass the server id returned from the XTStartTCPListener command.

XTStopTCPListener( myServer)

 

XTStartUDPListener

The XTStartUDPListener is used for receiving UDP datagrams. Only the port parameter is needed to startup the listener. Datagrams will be passed to the XTReceivedDatagram event. The only needed parameter is the port. The function will return an ID number if the open is successful and a 0 if there was an error. You should save the server id as you will need it to send datagrams, join or leave multicast groups and shutdown the server.

myServer = XTStartUDPListener( thePort)
if myServer == 0:
  XTWriteLog( “an error occurred trying to bind a new listener to port “ + str( thePort))

XTStopUDPListener

Pass the ID number you received from the XTStartUDPListener command.

XTStopUDPListener( myServer)

XTJoinMulticastGroup

Pass the ID number you received from the XTStartUPListener command and the name/address of the multicast group. Returns a boolean true if the join was successful.

if not XTJoinMulticastGroup( myServer, multicastAddress):
  XTWriteLog( “there was an error joining the multicast group”)
  

XTLeaveMulticastGroup

Pass the ID number you received from the XTStartUDPListener command and the name/address of the multicast group.

XTLeaveMulticastGroup( myServer, multicastAddress)
  

XTSendDatagram

Used to send a datagram through a UDP socket. Required parameters are the id of the server returned from the XTStartUDPListener or from the id passed in a received datagram event, the address you wish to send the packet to, the port you wish to send the packet to and finally the actual data you wish to send. In order to send a broadcast packet pass the xtBroadcastAddress constant instead of a specific IP address in the remoteAddress field.

XTSendDatagram( myServer, remoteAddress, remotePort, theData)

XTStartHTMLListener

The XTStartHTMLListener command can be used to startup an HTTP capable server. You will receive page request events along with all the data about the requester and any form data or post data, You can then send a response code and data. Page returns must be made inline as the connection is not kept open after the event returns.

Server Events

New Connection

The XTNewConnection event is called when a remote device is attempting to connect to the port you’re listening on. The function will receive 2 parameters, the first is a string and is the unique ID of the specific socket stream. This ID will be passed to you with every data packet reception and must be specified by you whenever you’re writing to an outgoing socket so that XTension knows which open pipe to send the data down. The second parameter is a python dictionary that contains as much data as is known about the connection and the remote host. Implementing this event is required to support incoming connections.

def XTNewConnection( theConnectionID, theConnectionInfo):
   XTWriteLog( “A new connection was received from address: “ + theConnectionInfo[ xtKeyRemoteAddress])
   return true # return true to accept the connection or false to force it closed immediately.
Connection Info Constants

The following keys into the dictionary are available for every connection:

  • xtKeyRemoteAddress the IPv4 address of the device connecting.
  • xtKeyRemotePort the port on which the connection was received. The same as the listening port of the server.
  • xtKeyName if the device is on the local network and has a bonjour name it will be included here. Otherwise it will be a “?“
  • xtKeyMacAddress If the device is on the local network and the local network supports Mac addressing then that number will be included here. If the connection is from outside the local network this will likely hold the MAC address of the router or all fields will be 00. Not all transport layers use mac addresses. Wifi and Ethernet do, but TCP over Firewire or thunderbolt do not and all fields will be 0 in those cases.
  • xtKeyUniqueId another copy of the sockets unique id same as passed directly to the event above.

Data Available

The data available call is similar to the XTDataAvailable event for a standard outgoing connection. The difference is that when made from a listening or script defined outgoing socket there will be 3 parameters as the connection ID and connection info dictionary will also be passed along with the received data. If you have started the server with a parsing boundary setting then these events will be called pre-parsed one event for each packet received. If not then it will be up to you to manage a buffer as there is no guarantee from TCP that each event will contain one packet, there may be partial packets or several together in one event. This handler is required for a script defined socket or listening interface.

def XTDataAvailable( theData, theConnectionID, theConnectionInfo):

Socket Error

If the connection throws an error the XTSocketError function will be called. This will pass 2 parameters the same as the XTNewConnection function but in this case the connection info dictionary will also contain 2 more keys for the error number and the error description if any. Note that this may also be called for normal disconnection of a connection with the appropriate error code. Use the other info in the info dictionary and or uniqueID to remove any saved references you have for the stream. After the processing of your error handler the socket will be closed and removed from the array of active connections. It is not necessary to also call the disconnect method.

def XTSocketError( theConnectionID, theConnectionInfo):
  if theConnectionInfo[ xtKeyErrorNumber] == 102:
     XTWriteLog( “the connection from Mac Address: “ + theConnectionInfo[ xtKeyMacAddress] + “ has been closed”)
  else:
     XTWriteLog( “error “ + str( theConnectionInfo[ xtKeyErrorNumber]) + “ “ + theConnectionInfo[ xtKeyErrorMessage] + “ has occurred.”)
     
   
Additional Error Constants
  • xtErrorNumber the integer error number that occurred, the most common possible errors are as follows:
    • 102 A disconnection notification. This will be called when the socket disconnects on purpose, but also if the connection was dropped for some other physical reason like someone tripping over the ethernet cable. The protocol should define some method to know if they are going to disconnect on purpose.
    • 103 Name resolution error. If connecting via a DNS name that cannot be resolved.
    • 106 Invalid state error. For things like trying to write to a socket that is not connected to anyone yet.
    • 107 Invalid port number. When trying to listen to a port that is below 1024 or above 65535. No listener running in an XTension plugin can bind to a port below 1024 as that requires running the interface with root privileges. You might accomplish this by forcing the python2.isf in the application bundle to run as root via a setuid command in the Terminal but I’m honestly not sure if modern MacOS versions will even allow this anymore as it’s a huge security hole. Pick a higher port.
    • 108 Out of memory. The attempt to allocate more buffer space has been refused by the system because there is no more memory available. You will never see this as long as things aren’t going horribly wrong with your system.
    • You may also encounter system level error numbers which you can look up here
  • xtErrorDescription A text description of the error code, similar to the above if available for the error number. A few of the more common lower level TCP errors may also be described.

The Interface Dictionary

For the entire list of constants in these objects please see the XTensionHelpers.py file in the example plugin:

Download sample plugin 6 Channel PWM Dimmer Kit Driver

plugins/07_keyedconstants.txt · Last modified: 2017/07/25 17:45 (external edit)