OK, I realized after a few miscommunications with John that while the APIs are documented, each action handler type has its own quirks that I'm not adequately documenting (yet). This guide is intended to help write effective action handlers, pointing out what actions are expected, what data flows through to where, etc. Note that all action handlers are strictly optional. Your client won't do much interesting without action handlers, but if you wanted to just set up a cutlass warez server, you could set it up to auto-accept all file requests, handle no actions, and it'll just sit there, sending and receiving files. If you want something that will interact with the user, though, action handlers are a must. The list of action types that you can set actions for is as follows. Not all of these actions are actually generated by the code yet, and those that are not are documented as not yet implemented below. Anyways, here's the list: CUT_USER_CONN_REQ - A remote user would like to connect to you CUT_USER_CONN - A remote user has connected to you CUT_USER_DROP - A remote user has disconnected the connection CUT_USER_TIMEOUT - A remote user has dropped due to timeout CUT_GRP_JOIN - A remote user has joined a group CUT_GRP_JOIN_REQ - A remote user has requested to join a group CUT_GRP_INVITE - You have been invited to a group CUT_GRP_LEAVE - A remote user has left a group CUT_MSG_RECV - You have received a remote text message CUT_FILE_OFFER - A remote user is offering you a file CUT_FILE_REQ - A remote user is requesting a file from you CUT_FILE_ACCEPT - A remote user has accepted your file offer CUT_FILE_REJECT - A remote user has rejected your file offer CUT_FILE_ABORT - An existing file tranfer has been aborted CUT_FILE_SEND_DONE - A file send transfer has been completed CUT_FILE_RECV_DONE - A file receive transfer has been completed CUT_SND_OFFER - A remote user is requesting an audio connection CUT_SND_ACCEPT - An audio connection has been established CUT_SND_REJECT - An audio connection has been rejected CUT_SND_DONE - An existing audio connection has been terminated CUT_SYS_MSG - Libcutlass has generated an internal message Each action handler type will be documented in greater detail below. Action objects that are passed through to action handlers have a wealth of data in them. You can extract said data with the cutlass_action_ functions. Note that not all fields are set on each action type. I will clearly mark out which fields are set in the action handler definitions. NOTE!!! Anything that returns a pointer to something is a potential memory leak. You must free these yourselves! uint8_t * cutlass_action_fingerprint (struct cut_action_obj *action_object); Returns the fingerprint of the key corresponding to the connection or group that generated the action. This can be used as either a conn_id or group_id in a response. It's a byte string of CUT_ID_LEN bytes length. char * cutlass_action_rnick(struct cut_action_obj *action_object); This returns the remote connection's nickname char * cutlass_action_gnick(struct cut_action_obj *action_object); This returns the remote group's group name. cutlass_public_key cutlass_action_rkey(struct cut_action_obj *action_object); This returns the remote connection's full key. cutlass_public_key cutlass_action_gkey(struct cut_action_obj *action_object); This returns the remote group's full key. char * cutlass_action_fname(struct cut_action_obj *action_object); This returns the file name of the associated file that generated the action. uint8_t * cutlass_action_fcsum(struct cut_action_obj *action_object); This returns the checksum of the associated file. uint32_t cutlass_action_fsize(struct cut_action_obj *action_object); This returns the size of the associated file. char * cutlass_action_msg(struct cut_action_obj *action_object); This returns the text message of the associated action. Note this is where we stick system messages, as well. struct in_addr * cutlass_action_addr(struct cut_action_obj *action_object); This is where we stick the address of the associated remote connection. int cutlass_action_type(struct cut_action_obj *action_object); This lets you know what type of action was generated, in case you have registered the same action handler for multiple action types. int cutlass_action_channel_id(struct cut_action_obj *action_object); This lets you know what channel the corresponding action is using. Useful for polling channels later. OK, that's all I have so far. As noted above, not all fields will be set on all action types. Please sanity check your variables before making use. They'll return NULL or zero if not set. Breaking doen the quirks of each individual action handler type: CUT_USER_CONN_REQ As yet unimplemented CUT_USER_CONN A remote user has connected to you, or your connection to a remote user was successful. This gets called after all KEX is complete. This requires no corresponding action on your part, but take the opportunity to let your user know that someone new is on the line. You can extract the following info: cutlass_action_fingerprint() cutlass_action_rkey() cutlass_action_addr() cutlass_action_type() Note that you might expect cutlass_action_rnick() to work here, but it doesn't, as we haven't yet exchanged info packets. CUT_USER_DROP A remote user has disconnected from you, and you will not longer be able to send messages to this connection. This requires no corresponding action on your part, but take the opportunity to let your user know that someone has vanished, or update your users list, wor whatever. You can extract the following info: cutlass_action_fingerprint() cutlass_action_rkey() cutlass_action_addr() cutlass_action_type() cutlass_action_rnick() CUT_USER_TIMEOUT Same as CUT_USER_DROP, but the disconnection has not occured via the normal shutdown process, but rather, they've exceeded the timeout limitation for responding to packets. You can extract the following info: cutlass_action_fingerprint() cutlass_action_rkey() cutlass_action_addr() cutlass_action_type() cutlass_action_rnick() CUT_GRP_JOIN As yet unimplemented CUT_GRP_JOIN_REQ As yet unimplemented CUT_GRP_INVITE As yet unimplemented CUT_GRP_LEAVE As yet unimplemented CUT_MSG_RECV You have received a text message from a remote host. You probably want to display this message, along with who it's from. Extract the message using cutlass_action_msg(). You can extract the following info: cutlass_action_fingerprint() cutlass_action_rkey() cutlass_action_addr() cutlass_action_type() cutlass_action_rnick() cutlass_action_msg() CUT_FILE_OFFER A remote user is offering you a file. If you have used cutlass_set_capabilities() to enable CAN_RECV_FILES, you really do need to handle this action. The two expected ways to handle this would be to call either cutlass_file_accept() or cutlass_file_reject(). Both of those calls take an action_object, and you can just pass through the action_object you were called with. If you're accepting the file, you'll notice a local_name parameter. This is the name you'll save the file under locally. You can pass a NULL pointer there, in which case the file name will remain unchanged, except for the directory (if any) will be stripped off, and the file will be placed in the current working directory. You can extract the following info: cutlass_action_fingerprint() cutlass_action_rkey() cutlass_action_addr() cutlass_action_type() cutlass_action_rnick() cutlass_action_fname() cutlass_action_fcsum() cutlass_action_fsize() cutlass_action_channel_id() You may want to save the fingerprint and channel_id, as you can use the pair of them to call cutlass_transport_poll later on to get up-to-date file transfer stats. CUT_FILE_REQ As yet unimplemented CUT_FILE_ACCEPT This action handler lets you know that the remote side has accepted the file transfer that you presumably offered (or they requested and you offered in response), and that the transfer is now actively transferring. Again, saving the fingerprint and channel_id may be useful here, if you haven't saved them already from cutlass_file_offer() (which takes the fingerprint as an argument and returns the channel_id, so you may well already have them). You can extract the following info: cutlass_action_fingerprint() cutlass_action_rkey() cutlass_action_addr() cutlass_action_type() cutlass_action_rnick() cutlass_action_fname() cutlass_action_fcsum() cutlass_action_fsize() cutlass_action_channel_id() CUT_FILE_REJECT This action handler lets you know that the remote side has rejected your file transfer. Let your user know the bad news. You can extract the following info: cutlass_action_fingerprint() cutlass_action_rkey() cutlass_action_addr() cutlass_action_type() cutlass_action_rnick() cutlass_action_fname() cutlass_action_fcsum() cutlass_action_fsize() cutlass_action_channel_id() CUT_FILE_ABORT As yet unimplemented CUT_FILE_SEND_DONE This action handler lets you know that the file you've been sending has been completely received by the other side. You can extract the following info: cutlass_action_fingerprint() cutlass_action_rkey() cutlass_action_addr() cutlass_action_type() cutlass_action_rnick() cutlass_action_fname() cutlass_action_fcsum() cutlass_action_fsize() cutlass_action_channel_id() CUT_FILE_RECV_DONE This action handler lets you know that the file you've been receiving has been completely processed, and the file descriptor is shut down, etc. You can extract the following info: cutlass_action_fingerprint() cutlass_action_rkey() cutlass_action_addr() cutlass_action_type() cutlass_action_rnick() cutlass_action_fname() cutlass_action_fcsum() cutlass_action_fsize() cutlass_action_channel_id() CUT_SYS_MSG This is the action handler that handles all internal libcutlass messages, errors and the like. If this action is unhandled, these messages will be dumped to stderr. If you'd like to pop up a box with an "OK" button for your users to read, though, this is the handler for you. The number of messages that pop up will depend on the verbosity level, set with cutlass_set_verbose(). If you're running at CUT_SUPAA_DEBUG, expect several messages every second/packet. You can extract the following info: cutlass_action_msg() CUT_SND_OFFER A remote user has attempted to open an audio connection to you. If you have used cutlass_set_capabilities() to enable CAN_RECV_AUDIO, and your permissions have been set to USER_ALLOW_CHECK, you ought to handle this action. The expected ways to handle this would be to call either cutlass_audio_accept() or cutlass_audio_reject(), and just pass through the action object that you were called with. You can extract the following info: cutlass_action_fingerprint() cutlass_action_addr() cutlass_action_type() cutlass_action_rnick() CUT_SND_ACCEPT An audio connection has been completed. This either occurs when a remote user accepts your offer made through cutlass_audio_connect(), or when you call cutlass_audio_accept() on a CUT_SND_OFFER action. (Or if you have your permissions set to ALL_ALLOWED on permit_audio, this will alert you that someone new has just joined your audio channel, and can pick up your heavy breathing RIGHT NOW!) You can extract the following info: cutlass_action_fingerprint() cutlass_action_addr() cutlass_action_type() cutlass_action_rnick() CUT_SND_REJECT The remote system has rejected your offer of audio, and no sending or receiving of audio will take place. Please call back later. (Or don't). You can extract the following info: cutlass_action_fingerprint() cutlass_action_addr() cutlass_action_type() cutlass_action_rnick() CUT_SND_DONE The audio connection has been closed by the remote side. However, the audio connection did once exist at one point. You can extract the following info: cutlass_action_fingerprint() cutlass_action_addr() cutlass_action_type() cutlass_action_rnick()