Sockets

 

Socket support allows you to create your own raw socket connections in order to send and receive information. You should already be an expert at writing Aliases, Popups, and Scripts before attempting to use sockets.

 

Sockets are a limited resource so it is important that you understand how these commands work before trying to use them. Sockets should always be closed after they have been used to make them available to other applications.

 

Socket Identifiers

 

$sock(name,N)

This returns information about a socket connection that you created using the socket commands.

 

Properties: name, ip, addr, port, status, sent, rcvd, sq, rq, ls, lr, mark, type, saddr, sport, to, wserr, wsmsg, bindip, bindport, ssl, pause, starttls

 

.name is the name you give to a connection to identify it

.addr original named address if one was used.

.sent and .rcvd return the number of bytes sent and rcvd over that connection so far

.sq and .rq return the number of bytes queued in the send and receive buffers respectively

.ls and .lr return the number of seconds since the connection last sent and last received info

.mark is a user storage area max. 512 bytes (see /sockmark)

.type returns the socket type, TCP or UDP

.saddr and .sport return the source address and port of the last received UDP packet

.to returns the number of seconds the socket has been open

.wserr returns the last winsock error number that occurred on a socket

.wsmsg returns the last winsock error message match the error number

.ssl returns $true for an SSL connection

.pause returns $true if a socket has been paused

.starttls returns $true for a STARTTLS connection

 

Note: You can use a wildcard name to quickly reference matching entries. The N parameter is optional, if it is not specified it is assumed to be 1.

 

$sockname

$sockname is the name given to a connection to identify it. This identifier can be used in events to know which connection an event is related to.

 

$sockerr

$sockerr is set to a value after each socket command/event and must be checked after each socket command and before processing an event to see if an error occurred.

 

$sockbr

$sockbr is set to the number of bytes read by a /sockread command. It is used to test whether any information was in fact read from the buffer (see below for more info).

 

Socket Commands and Events

 

The following information lists associated commands and script events together for easy reference.

 

Listening for and Accepting incoming connections

 

/socklisten [-dp] [bindip] <name> [port]

The /socklisten command listens on the specified port for connections to that port. If a port is not specified, the port is selected randomly from the range specified in the DCC Options dcc ports section.

 

The -d switch indicates that you specified an ip address as the bind address.

The -p switch enables UPnP support for the listening socket, if that is available.

 

on 1:socklisten:name:commands

The socklisten event is triggered when someone tries to connect to a port that you are listening on. If you want to accept the connection you must do it in this event using the /sockaccept command, otherwise the connection is closed.

 

/sockaccept <name>

The /sockaccept command accepts the current connection to your listening port and assigns it a name to identify it.

 

/sockrename <name> <newname>

The /sockrename command assigns a new name to an existing connection.

 

Opening and Closing connections

 

/sockopen [-de64nt] [bindip] <name> <address> <port>

The /sockopen command initiates a connection to the specified address and port. You can specify either an ip address or a named address (which will be resolved to an ip address).

 

The -d switch means that you specified an ip address as the bind address.

 

The -e switch creates an SSL connection.

 

The -46 switches are optional and specify the IPv4/IPv6 context when resolving named addresses.

 

The -n switch disables the Nagle algorithm for the connection.

 

The -t switch enables STARTTLS negotiation on a non-SSL connection.

 

on 1:sockopen:name:commands

The sockopen event is triggered when a /sockopen command is successful and a connection has been made.

 

/sockclose <name>

The /sockclose command closes the connection with the specified name. If you specify a wildcard name, all connections that match the wildcard are closed.

 

on 1:sockclose:name:commands

The sockclose event is triggered when a connection is closed by the remote connection (not you).

 

Sending information

 

/sockwrite [-tnba] <name> [numbytes] <text|%var|&binvar>

The /sockwrite command queues info to be sent on the specified connection. mIRC will then try to send that info as quickly as it can. Once it has finished sending the info, it triggers the on sockwrite event so you can send more info if you need to.

 

If you specify the -t switch, it forces mIRC to send anything beginning with a & as normal text instead of interpreting it as a binary variable. The -n switch appends a $crlf to the line being sent if it is not a &binvar and if it does not already have a $crlf.

 

The -b switch indicates that you are specifying the numbytes value which is the number of bytes you want sent.

 

The -a switch prevents characters in the range 0-255 from being UTF-8 encoded, as long as the line only contains characters in the range 0-255.

 

Note: You can use a wildcard name to send the same information at once to all connections that match the wildcard.

 

On error: if a /sockwrite fails, it sets $sock().wserr to the error value, and triggers the on sockwrite event with $sockerr set.

 

on 1:sockwrite:name:commands

The sockwrite event is triggered when mIRC has finished sending all of the data that you previously queued for sending or when the socket is ready for more writing.

 

Note: If you try to /sockwrite while there is still info queued in the send buffer, your new info will just be added to the end of the queue up to a maximum of 16384 bytes. Any attempt to queue more than that will result in an error message, so you should check how much info is currently queued by using $sock().sq (send queue) before trying to queue info on a socket.

 

Reading information

 

on 1:sockread:name:commands

The sockread event is triggered when there is info waiting to be read on the specified connection. You can read this info using the /sockread command.

 

Note: If this event triggers but no /sockread is performed to attempt to read the buffer, it is assumed that no script exists that is handling this buffer, so it is cleared and the info it contained is lost.

 

/sockread [-fn] [numbytes] <%var|&binvar>

The /sockread command reads bytes from the receive buffer into the specified variable.

 

If you specify a %var variable, a line of text ending with a Carriage Return/LineFeed is read into %var. The $crlf are stripped off (this may result in %var being $null if the line only consisted of $crlf).

 

If you specify a &binvar then [numbytes] of info is read into the binary variable. If no [numbytes] is specified it defaults to 4096 bytes.

 

If you specify the -f switch with a %var variable, this forces mIRC to fill the %var variable with whatever text is in the receive buffer, even if it does not end in a $crlf. If you attempt to use this with binary data, it will only read up to the first NULL byte.

 

The -n switch allows you to read a $crlf terminated line into a &binvar. If the incoming line does not contain a $crlf, no bytes will be read into &binvar, unless you specify the -f switch, which forces the read (same as when reading into %vars).

 

Note: A single /sockread may not be enough to read the entire buffer. You should keep reading until $sockbr (bytes read) is set to zero. This is far faster than letting mIRC re-trigger the event. If your script does not read the whole buffer, the on sockread event is re-triggered if:

 a) you were reading into a &binvar.

 b) you were reading into a %var and there is still a $crlf terminated line in the buffer waiting to be read.

 

Example:

This example shows you how you should process a sockread event. The socket has already been opened and has received information, so the sockread event is triggered. The socket name is testing. There is an explanation of each step below the sample script.

 

on 1:sockread:testing:{

 if ($sockerr > 0) return

 :nextread

 sockread %temp

 if ($sockbr == 0) return

 if (%temp == $null) %temp = -

 echo 4 %temp

 goto nextread

}

 

If $sockerr is larger than zero then there is a socket error. mIRC will automatically close the socket, so all you have to do is return from the event.

 

sockread %temp reads a $crlf terminated line of text and stores it in %temp. If the buffer did not contain a $crlf terminated line, %temp is not filled with anything, and $sockbr returns zero, so you should just return from the event without further processing.

 

If %temp is $null then that means the line consisted only of a $crlf which mIRC has automatically stripped out of the line, so only an empty line remains. In this case, I am setting %temp to a dash to represent an empty line but you can do whatever you wish here.

 

I then echo the final line that was read to the status window.

 

Finally, I use goto to jump back and to continue reading remaining lines in the socket's receive buffer.

 

Pausing a socket

 

/sockpause [-r] <name>

The /sockpause command pauses/restarts a socket when reading incoming data.

 

Marking a socket

 

/sockmark <name> [text]

The /sockmark command fills the .mark attribute of a socket with the specified info for later reference via the $sock().mark property. If you do not specify any text, the mark is cleared. The mark can hold up to 512 bytes.

 

Note: You can use a wildcard name to set the same information at once for all connections that match the wildcard.

 

Listing open sockets

 

/socklist [-tul] [name]

The /socklist command lists all open sockets, or if you specify the -tul switches, it lists tcp, udp, and listening sockets respectively. You can also specify a socket name or wildcard.

 

UDP Sockets

UDP is a connection-less protocol, ie. you can send information via UDP to other UDP addresses without needing to connect to them first.

 

UDP does not guarantee that any information you send will actually reach its destination, ie. it is not a reliable protocol. Also, be aware that UDP packets may not arrive in the same order as that in which they were sent. This means that you must perform your own checking to confirm that any data you sent actually reached its destination properly.

 

/sockudp [-bntkd] [bindip] <name> [port] <ipaddress> <port> [numbytes] [text|%var|&binvar]

 

If you specify the -t switch, it forces mIRC to send anything beginning with a & as normal text instead of interpreting it as a binary variable. The -n switch appends a $crlf to the line being sent if it is not a &binvar and if it does not already have a $crlf.

 

The -b switch indicates that you are specifying the numbytes value which is the number of bytes you want sent.

 

The -k switch forces the socket to stay open, this allows it to listen for data that is sent to its port via UDP. If -k is not specified, the socket is opened, the information is sent to the specified ipaddress and port, and the socket is then closed.

 

The -d switch means that you specified an ip address as the bind address.

 

If you specify a socket name that does not exist, it is created. If it does exist, the existing socket is used to send the info.

 

You can also specify the local port number that you wish to use, if it is not specified, mIRC chooses one randomly.

 

ipaddress and port specify the destination address to which you want to send information. You can only use an IP address here.

 

On error: if a /sockudp fails, it sets $sock().wserr to the error value, and triggers the on sockwrite event with $sockerr set.

 

on 1:udpread:name:commands

The udpread event is triggered when there is info waiting to be read on a UDP socket. You can read this info using the /sockread command.

 

Note: If this event triggers but no /sockread is performed to attempt to read the buffer, it is assumed that no script exists that is handling this buffer, so it is cleared and the info it contained is lost.

 

Other commands and identifiers

The following network-related commands and identifiers are also available.

 

/bindip [on|off] <ipaddress>

This command allows you to change the bind settings in the Ports dialog. An adapter name can be specified instead of the IP address.

 

$bindip(N|ipaddress)

Returns the list of active network adapters. The N = 0, returns the total number of active network adapters.

 

Properties: name, ip, loopback

 

If an IP address is specified, returns the best network adapter for connecting to that IP address.

 

$portfree(N,[ipaddress])

Returns $true if the specified port number is not in use, where N = port number, otherwise returns $false.

 

If an IP address is specified, only the interface with that IP address is checked for used ports, otherwise all active interfaces are checked. An adapter name can also be used instead of an IP address.

 

$iptype(text)

Returns "ipv4" or "ipv6" if text is is a valid IP address format.

 

Properties: compress, expand

 

With IPv6 addresses, the properties .compress and .expand can be used.