From 0c6ac05d58c082e6fb50c876f1940ce5d29887af Mon Sep 17 00:00:00 2001
From: Maxim Kochetkov <fido_max@inbox.ru>
Date: Thu, 27 Nov 2014 10:59:40 +0300
Subject: [PATCH 1/2] + RAWCAN SocketCAN support

---
 src/moduls/transport/Sockets/po/ru.po   | 109 +++++++++++++-------------------
 src/moduls/transport/Sockets/socket.cpp |  93 +++++++++++++++++++++++++++
 src/moduls/transport/Sockets/socket.h   |   2 +
 3 files changed, 140 insertions(+), 64 deletions(-)

diff --git a/src/moduls/transport/Sockets/po/ru.po b/src/moduls/transport/Sockets/po/ru.po
index 49d1eaf..c974b71 100644
--- a/src/moduls/transport/Sockets/po/ru.po
+++ b/src/moduls/transport/Sockets/po/ru.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: OpenSCADA.Transport.Sockets 1.5.0\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-02-01 20:38+0200\n"
+"POT-Creation-Date: 2014-11-27 10:57+0300\n"
 "PO-Revision-Date: 2007-10-19 18:04+0300\n"
 "Last-Translator: Roman Savochenko <rom_as@oscada.org>\n"
 "Language-Team: <ru@li.org>\n"
@@ -16,127 +16,112 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 
-#: socket.cpp:45
 msgid "Sockets"
 msgstr "Сокеты"
 
-#: socket.cpp:49
 msgid "Roman Savochenko"
 msgstr "Роман Савоченко"
 
-#: socket.cpp:50
 msgid ""
 "Allow sockets based transport. Support inet and unix sockets. Inet socket "
 "use TCP and UDP protocols."
-msgstr ""
-"Предоставляет транспорт основанный на сокетах. Поддерживаются интернет и "
+msgstr "Предоставляет транспорт основанный на сокетах. Поддерживаются интернет и "
 "UNIX сокеты. Интернет сокет использует TCP и UDP протоколы."
 
-#: socket.cpp:108 socket.cpp:109
 msgid "Addition parameters"
 msgstr "Дополнительные параметры"
 
-#: socket.cpp:148
 #, c-format
 msgid ""
 "Connections %d, opened %d. Traffic in %s, out %s. Closed connections by "
 "limit %d."
-msgstr ""
-"Соединений %d, открыто %d. Трафик входящий %s, исходящий %s. Закрыто "
+msgstr "Соединений %d, открыто %d. Трафик входящий %s, исходящий %s. Закрыто "
 "соединений по лимиту %d."
 
-#: socket.cpp:200 socket.cpp:208 socket.cpp:214
 #, c-format
 msgid "Error create '%s' socket!"
 msgstr "Ошибка создания сокета '%s'!"
 
-#: socket.cpp:217
 #, c-format
 msgid "Socket type '%s' error!"
 msgstr "Ошибка типа '%s' сокета!"
 
-#: socket.cpp:232 socket.cpp:775
 #, c-format
 msgid "Socket name '%s' error!"
 msgstr "Ошибка имени '%s' сокета!"
 
-#: socket.cpp:249
 #, c-format
 msgid "TCP socket doesn't bind to '%s'!"
 msgstr "TCP сокет не подключился к '%s'!"
 
-#: socket.cpp:265
 #, c-format
 msgid "UDP socket doesn't bind to '%s'!"
 msgstr "UDP сокет не подключился к '%s'!"
 
-#: socket.cpp:282
 #, c-format
 msgid "UNIX socket doesn't bind to '%s'!"
 msgstr "UNIX сокет не подключился к '%s'!"
 
-#: socket.cpp:318
+msgid "RAWCAN socket doesn't bind to '%s'!"
+msgstr "RAWCAN сокет не подключился к '%s'!"
+
+msgid "RAWCAN socket binded '%s'!"
+msgstr "RAWCAN сокет подключен к '%s'!"
+
 #, c-format
 msgid "Socket write message '%d'."
 msgstr "Сокет записал сообщение '%d'."
 
-#: socket.cpp:324 socket.cpp:514
 msgid "Write: reply for zero bytes."
 msgstr "Запись: ответ ноль байт."
 
-#: socket.cpp:334 socket.cpp:524
 #, c-format
 msgid "Write: error '%s (%d)'!"
 msgstr "Запись: ошибка '%s (%d)'!"
 
-#: socket.cpp:374
 #, c-format
 msgid "Close input transport by error: %s"
 msgstr "Закрытие входного транспорта по ошибке: %s!"
 
-#: socket.cpp:402 socket.cpp:427
 msgid "Error creation of the thread!"
 msgstr "Ошибка создания потока!"
 
-#: socket.cpp:441
 #, c-format
 msgid "Socket received datagram '%d' from '%s'!"
 msgstr "Сокет получил датаграму '%d' из '%s'!"
 
-#: socket.cpp:447
 #, c-format
 msgid "Socket replied datagram '%d' to '%s'!"
 msgstr "Сокет ответил датаграмой '%d' в '%s'!"
 
-#: socket.cpp:463
+#, c-format
+msgid ""
+"Socket received can frame id:<%08X> dlc: <%d> data:%02X%02X%02X%02X%02X%02X"
+"%02X%02X!"
+msgstr ""
+
 msgid " client task is stopping...."
 msgstr " клиентская задача остановлена...."
 
-#: socket.cpp:477
 #, c-format
 msgid "Socket has been connected by '%s'!"
 msgstr "К сокету подключился '%s'!"
 
-#: socket.cpp:502
 #, c-format
 msgid "Socket received message '%d' from '%s'."
 msgstr "Сокет получил сообщение '%d' из '%s'."
 
-#: socket.cpp:509
 #, c-format
 msgid "Socket replied message '%d' to '%s'."
 msgstr "Сокет ответил сообщением '%d' на '%s'."
 
-#: socket.cpp:551
 #, c-format
 msgid "Socket has been disconnected by '%s'!"
 msgstr "От сокета отключился '%s'!"
 
-#: socket.cpp:588
 msgid "Error request to protocol."
 msgstr "Ошибка запроса к протоколу."
 
-#: socket.cpp:624
 msgid ""
 "Socket's input transport has address format:\n"
 "  TCP:{addr}:{port}:{mode} - TCP socket:\n"
@@ -148,11 +133,14 @@ msgid ""
 "    addr - address for socket to be opened, empty address opens socket for "
 "all interfaces;\n"
 "    port - network port (/etc/services).\n"
+"  RAWCAN:{if}:{mask}:{id} - CAN socket:\n"
+"    if - interface name;\n"
+"    mask - can frame id mask;\n"
+"    id - can id;\n"
 "  UNIX:{name}:{mode} - UNIX socket:\n"
 "    name - UNIX-socket's file name;\n"
 "    mode - work mode (0 - break connection; 1 - keep alive)."
-msgstr ""
-"Входной транспорт Socket имеет формат адреса:\n"
+msgstr "Входной транспорт Socket имеет формат адреса:\n"
 "  TCP:{addr}:{port}:{mode} - TCP сокет:\n"
 "    addr - адрес открытия сокета, пустой адрес открывает сокет на всех "
 "интерфейсах;\n"
@@ -163,111 +151,99 @@ msgstr ""
 "    addr - адрес открытия сокета, пустой адрес открывает сокет на всех "
 "интерфейсах;\n"
 "    port - сетевой порт (/etc/services).\n"
+"  RAWCAN:{if}:{mask}:{id} - CAN socket:\n"
+"    if - имя интерфейса;\n"
+"    mask - маска can;\n"
+"    id - идентификатор can;\n"
 "  UNIX:{name}:{mode} - UNIX сокет:\n"
 "    name - Имя файла UNIX-сокета;\n"
 "    mode - режим работы (0 - разрывать соединение; 1 - сохранять соединение)."
 
-#: socket.cpp:636
 msgid "Queue length"
 msgstr "Длина очереди"
 
-#: socket.cpp:637 socket.cpp:639
 msgid "Used for TCP and UNIX sockets."
 msgstr "Используется для TCP и UNIX сокетов."
 
-#: socket.cpp:638
 msgid "Clients maximum"
 msgstr "Максимум клиентов"
 
-#: socket.cpp:640
 msgid "Input buffer (kbyte)"
 msgstr "Входной буфер (кбайт)"
 
-#: socket.cpp:641
 msgid "Priority"
 msgstr "Приоритет"
 
-#: socket.cpp:643
 msgid "Keep alive requests"
 msgstr "Keep alive запросов"
 
-#: socket.cpp:644
 msgid ""
 "Close the connection after specified requests.\n"
 "Zero value for disable (not close ever)."
-msgstr ""
-"Закрытие подключения после указанного количества запросов.\n"
+msgstr "Закрытие подключения после указанного количества запросов.\n"
 "Нулевое значение для отключения (не закрывается никогда)."
 
-#: socket.cpp:645
 msgid "Keep alive timeout (s)"
 msgstr "Keep alive время ожидания (с)"
 
-#: socket.cpp:646
 msgid ""
 "Close the connection after no requests at specified timeout.\n"
 "Zero value for disable (not close ever)."
-msgstr ""
-"Закрытие подключения после отсутствия запросов в течении указанного времени.\n"
+msgstr "Закрытие подключения после отсутствия запросов в течении указанного "
+"времени.\n"
 "Нулевое значение для отключения (не закрывается никогда)."
 
-#: socket.cpp:720
 #, c-format
 msgid "Traffic in %s, out %s."
 msgstr "Трафик входящий %s, исходящий %s."
 
-#: socket.cpp:762
 #, c-format
 msgid "Type socket '%s' error!"
 msgstr "Ошибка в типе '%s' сокета!"
 
-#: socket.cpp:789
+#, fuzzy
+msgid "Error force socket %d using: %s!"
+msgstr "Ошибка  сокета %d: %s!"
+
 #, c-format
 msgid "Error creation TCP socket: %s!"
 msgstr "Ошибка создания TCP сокета: %s!"
 
-#: socket.cpp:796
 #, c-format
 msgid "Error creation UDP socket: %s!"
 msgstr "Ошибка создания UDP сокета: %s!"
 
-#: socket.cpp:816
 #, c-format
 msgid "Connect to Internet socket error: %s!"
 msgstr "Ошибка подключения к Internet сокету: %s!"
 
-#: socket.cpp:829
 #, c-format
 msgid "Error creation UNIX socket: %s!"
 msgstr "Ошибка создания UNIX сокета: %s!"
 
-#: socket.cpp:834
 #, c-format
 msgid "Connect to UNIX error: %s!"
 msgstr "Ошибка подключения к UNIX сокету: %s!"
 
-#: socket.cpp:864
+msgid "RAWCAN socket doesn't bind to <%s>!"
+msgstr "RAWCAN сокет не подключился к <%s>!"
+
 msgid "Unknown error"
 msgstr "Неизвестная ошибка"
 
-#: socket.cpp:877
 msgid "Transport is not started!"
 msgstr "Транспорт не запущен!"
 
-#: socket.cpp:880
 #, c-format
 msgid "Request error: %s"
 msgstr "Ошибка запроса: %s"
 
-#: socket.cpp:927
 msgid "Timeouted!"
 msgstr "Время ожидания истекло!"
 
-#: socket.cpp:928
 msgid "Socket error!"
 msgstr "Ошибка сокета!"
 
-#: socket.cpp:958
 msgid ""
 "Socket's output transport has address format:\n"
 "  TCP:{addr}:{port} - TCP socket:\n"
@@ -276,31 +252,36 @@ msgid ""
 "  UDP:{addr}:{port} - UDP socket:\n"
 "    addr - address for remote socket to be opened;\n"
 "    port - network port (/etc/services).\n"
+"  RAWCAN:{if}:{mask}:{id} - CAN socket:\n"
+"    if - interface name;\n"
+"    mask - can frame id mask;\n"
+"    id - can id;\n"
 "  UNIX:{name} - UNIX socket:\n"
 "    name - UNIX-socket's file name."
-msgstr ""
-"Выходной транспорт Socket имеет формат адреса:\n"
+msgstr "Выходной транспорт Socket имеет формат адреса:\n"
 "  TCP:{addr}:{port} - TCP сокет:\n"
 "    addr - адрес для открытия удалённого сокета;\n"
 "    port - сетевой порт (/etc/services);\n"
 "  UDP:{addr}:{port} - UDP сокет:\n"
 "    addr - адрес для открытия удалённого сокета;\n"
 "    port - сетевой порт (/etc/services);\n"
+"  RAWCAN:{if}:{mask}:{id} - CAN socket:\n"
+"    if - имя интерфейса;\n"
+"    mask - маска can;\n"
+"    id - идентификатор can;\n"
 "  UNIX:{name} - UNIX сокет:\n"
 "    name - Имя файла UNIX-сокета."
 
-#: socket.cpp:967
 msgid "Timings"
 msgstr "Временные интервалы"
 
-#: socket.cpp:968
 msgid ""
 "Connection timings in format: \"conn:next[:rep]\". Where:\n"
 "    conn - maximum time for connection respond wait, in seconds;\n"
 "    next - maximum time for continue respond wait, in seconds;\n"
 "    rep  - minimum repeate timeout, in seconds."
-msgstr ""
-"Временные интервалы соединения в формате: \"conn:next[:rep]\". Где:\n"
+msgstr "Временные интервалы соединения в формате: \"conn:next[:rep]\". Где:\n"
 "    conn - максимальное время ожидания ответа соединения, в секундах;\n"
 "    next - максимальное время ожидания продолжения ответа, в секундах;\n"
 "    rep  - минимальный таймаут ожидания повтора запроса, в секундах."
+
diff --git a/src/moduls/transport/Sockets/socket.cpp b/src/moduls/transport/Sockets/socket.cpp
index 2ffa394..43a3849 100644
--- a/src/moduls/transport/Sockets/socket.cpp
+++ b/src/moduls/transport/Sockets/socket.cpp
@@ -20,15 +20,29 @@
 
 #include <sys/types.h>
 #include <sys/un.h>
+#include <sys/ioctl.h>
 #include <netinet/in.h>
 #include <netdb.h>
 #include <sys/socket.h>
 #include <sys/wait.h>
 #include <sys/select.h>
 #include <arpa/inet.h>
+#include <net/if.h>
+
+#include <linux/can.h>
+#include <linux/can/raw.h>
+
+#ifndef PF_CAN
+#define PF_CAN 29
+#endif
+
+#ifndef AF_CAN
+#define AF_CAN PF_CAN
+#endif
 
 #include <fcntl.h>
 #include <unistd.h>
+#include <getopt.h>
 #include <string>
 #include <errno.h>
 
@@ -196,6 +210,11 @@ void TSocketIn::start( )
 	    throw TError(nodePath().c_str(), _("Error create '%s' socket!"), s_type.c_str());
 	type = SOCK_UNIX;
     }
+    else if(s_type == S_NM_RAWCAN) {
+	if ((sock_fd = socket( PF_CAN, SOCK_RAW, CAN_RAW)) == -1)
+		throw TError(nodePath().c_str(), _("Error create '%s' socket!"), s_type.c_str());
+	type = SOCK_RAWCAN;
+	}
     else throw TError(nodePath().c_str(), _("Socket type '%s' error!"), s_type.c_str());
 
     if(type == SOCK_TCP || type == SOCK_UDP) {
@@ -257,6 +276,28 @@ void TSocketIn::start( )
 	}
 	listen(sock_fd, maxQueue());
     }
+ 	else if(type == SOCK_RAWCAN) {
+		path	= TSYS::strSepParse(addr(), 1, ':');
+		struct can_filter rfilter;
+		rfilter.can_id = strtoul(TSYS::strSepParse(addr(), 2, ':').c_str(), NULL, 0);
+		rfilter.can_mask = strtoul(TSYS::strSepParse(addr(), 3, ':').c_str(), NULL, 0);
+		setsockopt(sock_fd, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));
+		if (!path.size())
+			path = "can0";
+		struct ifreq ifr;
+		strcpy(ifr.ifr_name, path.c_str());
+		ioctl(sock_fd, SIOCGIFINDEX, &ifr); 
+		struct sockaddr_can name_can;
+		name_can.can_family = AF_CAN;
+		name_can.can_ifindex = ifr.ifr_ifindex;
+		if (bind(sock_fd, (struct sockaddr*) &name_can, sizeof(name_can)) == -1) {
+			close(sock_fd);
+			throw TError(nodePath().c_str(), _("RAWCAN socket doesn't bind to '%s'!"), addr().c_str());
+		} else {
+			if (mess_lev() == TMess::Debug)
+				mess_debug(nodePath().c_str(), _("RAWCAN socket binded '%s'!"), addr().c_str());
+		}
+	}
 
     SYS->taskCreate(nodePath('.',true), taskPrior(), Task, this);
 
@@ -417,6 +458,26 @@ void *TSocketIn::Task( void *sock_in )
 	    r_len = sendto(sock->sock_fd, answ.c_str(), answ.size(), 0, (sockaddr *)&name_cl, name_cl_len);
 	    sock->trOut += vmax(0,r_len);
 	}
+	else if (sock->type == SOCK_RAWCAN) {
+			int r_len;
+			struct can_frame frame;
+			string req, answ;
+			r_len = recv(sock->sock_fd, &frame, sizeof(frame), 0);
+			sock->trIn += r_len;
+			if (r_len <= 0)
+				continue;
+			req.assign((char *) frame.data, frame.can_dlc);
+
+			if (mess_lev() == TMess::Debug)
+				mess_debug(sock->nodePath().c_str(), _("Socket received can frame id:<%08X> dlc: <%d> data:%02X%02X%02X%02X%02X%02X%02X%02X!"), frame.can_id,
+						frame.can_dlc, frame.data[0], frame.data[1], frame.data[2], frame.data[3], frame.data[4], frame.data[5], frame.data[6], frame.data[7]);
+			sock->messPut(sock->sock_fd, req, answ, TSYS::uint2str(frame.can_id), prot_in);
+			if (!prot_in.freeStat())
+				continue;
+
+		    r_len = send(sock->sock_fd, answ.c_str(), answ.size(), 0);
+		    sock->trOut += vmax(0,r_len);
+		}
     }
     pthread_attr_destroy(&pthr_attr);
 
@@ -587,6 +648,10 @@ void TSocketIn::cntrCmdProc( XMLNode *opt )
 	    "  UDP:{addr}:{port} - UDP socket:\n"
 	    "    addr - address for socket to be opened, empty address opens socket for all interfaces;\n"
 	    "    port - network port (/etc/services).\n"
+		"  RAWCAN:{if}:{mask}:{id} - CAN socket:\n"
+		"    if - interface name;\n"
+		"    mask - can frame id mask;\n"
+		"    id - can id;\n"
 	    "  UNIX:{name}:{mode} - UNIX socket:\n"
 	    "    name - UNIX-socket's file name;\n"
 	    "    mode - work mode (0 - break connection; 1 - keep alive)."));
@@ -708,6 +773,7 @@ void TSocketOut::start( int itmCon )
     else if(s_type == S_NM_TCP)	type = SOCK_TCP;
     else if(s_type == S_NM_UDP)	type = SOCK_UDP;
     else if(s_type == S_NM_UNIX)type = SOCK_UNIX;
+	else if (s_type == S_NM_RAWCAN) type = SOCK_RAWCAN;
     else throw TError(nodePath().c_str(),_("Type socket '%s' error!"),s_type.c_str());
 
     if(type == SOCK_FORCE) {
@@ -786,6 +852,29 @@ void TSocketOut::start( int itmCon )
 	}
 	fcntl(sock_fd, F_SETFL, fcntl(sock_fd,F_GETFL,0)|O_NONBLOCK);
     }
+	else if (type == SOCK_RAWCAN) {
+		if ((sock_fd = socket( PF_CAN, SOCK_RAW, CAN_RAW)) == -1)
+			throw TError(nodePath().c_str(), _("Error create '%s' socket!"), s_type.c_str());
+		int flags = fcntl(sock_fd, F_GETFL, 0);
+		fcntl(sock_fd, F_SETFL, flags | O_NONBLOCK);;
+		string path = TSYS::strSepParse(addr(), 1, ':');
+		struct can_filter rfilter;
+		rfilter.can_id = strtoul(TSYS::strSepParse(addr(), 2, ':').c_str(), NULL, 0);
+		rfilter.can_mask = strtoul(TSYS::strSepParse(addr(), 3, ':').c_str(), NULL, 0);
+		setsockopt(sock_fd, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));
+		if (!path.size())
+			path = "can0";
+		struct ifreq ifr;
+		strcpy(ifr.ifr_name, path.c_str());
+		ioctl(sock_fd, SIOCGIFINDEX, &ifr); 
+		struct sockaddr_can name_can;
+		name_can.can_family = AF_CAN;
+		name_can.can_ifindex = ifr.ifr_ifindex;
+		if (bind(sock_fd, (struct sockaddr*) &name_can, sizeof(name_can)) == -1) {
+			close(sock_fd);
+			throw TError(nodePath().c_str(), _("RAWCAN socket doesn't bind to <%s>!"), addr().c_str());
+		}
+	}
 
     mLstReqTm = TSYS::curTime();
 
@@ -910,6 +999,10 @@ void TSocketOut::cntrCmdProc( XMLNode *opt )
 	    "  UDP:{addr}:{port} - UDP socket:\n"
 	    "    addr - address for remote socket to be opened;\n"
 	    "    port - network port (/etc/services).\n"
+		"  RAWCAN:{if}:{mask}:{id} - CAN socket:\n"
+		"    if - interface name;\n"
+		"    mask - can frame id mask;\n"
+		"    id - can id;\n"
 	    "  UNIX:{name} - UNIX socket:\n"
 	    "    name - UNIX-socket's file name."));
 	ctrMkNode("fld",opt,-1,"/prm/cfg/TMS",_("Timings"),RWRWR_,"root",STR_ID,2,"tp","str","help",
diff --git a/src/moduls/transport/Sockets/socket.h b/src/moduls/transport/Sockets/socket.h
index 04288c8..291775f 100644
--- a/src/moduls/transport/Sockets/socket.h
+++ b/src/moduls/transport/Sockets/socket.h
@@ -32,11 +32,13 @@
 #define S_NM_TCP	"TCP"
 #define S_NM_UDP	"UDP"
 #define S_NM_UNIX	"UNIX"
+#define S_NM_RAWCAN "RAWCAN"
 
 #define SOCK_FORCE	-1
 #define SOCK_TCP	0
 #define SOCK_UDP	1
 #define SOCK_UNIX	2
+#define SOCK_RAWCAN  3
 
 using namespace OSCADA;
 
-- 
1.9.1


From d5b330fc27cb3a16b051adc02beb904f4f49c030 Mon Sep 17 00:00:00 2001
From: Maxim Kochetkov <fido_max@inbox.ru>
Date: Thu, 27 Nov 2014 11:06:58 +0300
Subject: [PATCH 2/2] * russian translation fixed

---
 src/moduls/transport/Sockets/po/ru.po | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/moduls/transport/Sockets/po/ru.po b/src/moduls/transport/Sockets/po/ru.po
index c974b71..75b60b9 100644
--- a/src/moduls/transport/Sockets/po/ru.po
+++ b/src/moduls/transport/Sockets/po/ru.po
@@ -98,7 +98,8 @@ msgstr "Сокет ответил датаграмой '%d' в '%s'!"
 msgid ""
 "Socket received can frame id:<%08X> dlc: <%d> data:%02X%02X%02X%02X%02X%02X"
 "%02X%02X!"
-msgstr ""
+msgstr "Сокет получил  can сообщение id:<%08X> dlc: <%d> data:%02X%02X%02X%02X%02X%02X"
+"%02X%02X!"
 
 msgid " client task is stopping...."
 msgstr " клиентская задача остановлена...."
-- 
1.9.1

