I wrote small and simple C program which simply sends information about torrent completion to Snarl client (for usage with script-torrent-done-filename setting of Transmission). Please enable Network notifications in Snarl settings before using it. It does not register any App or notification class, and use "Anonymous Notification" feature, because of my laziness.
Tested with transmission 2.04 and Snarl R2.3.
Pardon my code comments (they are in polish), I was too lazy to remove them, because most parts are adapted from simple network client which I wrote for network programming at my University.
As you can see IP of client and port are hardcoded, so change them to whatever suits you before compiling (9887 is default port for snarl).
Process is forked into background because of hangup of transmission when using external completion script (especially when client isn't working on remote machine - before socket timeout).
Code: Select all
const char* host = "192.168.1.12"; // adres ip na ktorym jest uruchomiony serwer
const int port = 9887; // port na ktorym dziala serwer
#include <stdlib.h> /* definicje kodów błędów zwracanych przez funkcje main() EXIT_ itp. */
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
int main(void) {
if (fork() != 0) { exit(0); } else {
close(0); close(1); close(2);
setpgrp();
const int sock = socket(AF_INET, SOCK_STREAM, 0); // tworzymy nowe gniazdo
struct sockaddr_in addr; // adres gniazda
char buf[512]; // bufor
int len; // dlugosc bufora
if (sock == -1) { // jesli nie udalo sie utworzyc gniazda
//perror("blad w sock()"); // wypisujemy blad
return EXIT_FAILURE; // zwracamy kod bledu i zakanczamy program
}
// printf("jest socket");
addr.sin_family = AF_INET; // rodzina adresow - tutaj internetowe
addr.sin_port = htons(port); // port na ktorym ma dzialac serwer
// uzywamy funkcji htons aby przeksztalcic liczbe
// w lokalnej kolejnosci bajtow na kolejnosc sieciowa
addr.sin_addr.s_addr = inet_addr(host); // ustawiamy adres sieciowy naszej struktury
// za pomoca funkcji inet_addr ktora konwertuje
// stringa z adresem do odpowiedniej liczby
// podlaczamy sie z pomoca socketa i od razu sprawdzamy czy nie wystapil blad (-1)
if (connect(sock, (struct sockaddr*) &addr, sizeof(addr)) == -1) {
//perror("blad w connect()"); // zwracamy blad
return EXIT_FAILURE; // i kod bledu
}
sprintf(buf, "type=SNP#?version=1.0#?action=notification#?app=Transmission#?title=Transmission (Torrent Completed)#?text=%s at %s#?timeout=10\r\0", getenv("TR_TORRENT_NAME"), getenv("TR_TIME_LOCALTIME"));
len = strlen(buf); // ustawiamy zmienna len na dlugosc bufor
// zapisujemy dane do gniazda, jesli funkcja zwroci -1 to blad
if (write(sock, buf, len) == -1) {
// perror("blad w write()"); // wypisujemy blad
return EXIT_FAILURE; // zwracamy kod bledu
}
// printf("jest wyslane");
}
}