so I am writing a basic server that clients can connect to. I'm testing it with telnet, but my issue is how I store my clients in a list, so I could then print out who is connected to the server. I've tried using the ++ operator on a list that stores clients, but I keep getting a process error.
Here is my code so far:
cell_process()->
io:fwrite("In cell~n"),
{ok,Listening_socket} = gen_tcp:listen(21,
[binary,
{backlog,5},
{active,false},
{packet,line}]),
loop(Listening_socket).
loop(Listening_socket)->
case gen_tcp:accept(Listening_socket) of
{ok,Client_socket} ->
gen_tcp:send(Client_socket, "Hello, what is your name?"),
{_,Name} = gen_tcp:recv(Client_socket,0),
gen_tcp:send(Client_socket, "Hello, "),
gen_tcp:send(Client_socket, Name),
io:fwrite([Name]),
spawn(fun()-> client_loop(Client_socket) end),
loop(Listening_socket);
{error,Why}->io:fwrite("Error: "),
io:fwrite([Why])
end.
client_loop(Client_socket)->
case gen_tcp:recv(Client_socket,0) of
{ok,Message}-> gen_tcp:send(Client_socket,Message),
%% code not yet implemented here
client_loop(Client_socket);
{error,Why}-> io:fwrite("Error: ~s~n",[Why]),
gen_tcp:close(Client_socket)
end.
Any help would be much appreciated, thanks for reading.
To keep a trace of connected clients you have to add a variable to the loop function, and store any relevant information in a Clients list as you suggest.
cell_process()->
io:fwrite("In cell~n"),
{ok,Listening_socket} = gen_tcp:listen(21,
[binary,
{backlog,5},
{active,false},
{packet,line}]),
loop(Listening_socket,[]). %% initial Clients list is empty
loop(Listening_socket,Clients)->
case gen_tcp:accept(Listening_socket) of
{ok,Client_socket} ->
gen_tcp:send(Client_socket, "Hello, what is your name?"),
{_,Name} = gen_tcp:recv(Client_socket,0),
gen_tcp:send(Client_socket, "Hello, "),
gen_tcp:send(Client_socket, Name),
io:fwrite([Name]),
Pid = spawn(fun()-> client_loop(Client_socket) end),
loop(Listening_socket,[{Pid,Client_socket,Name}|Clients]);
%% add new Client to the lists But see my comment
{error,Why}->io:fwrite("Error: "),
io:fwrite([Why])
end.
client_loop(Client_socket)->
case gen_tcp:recv(Client_socket,0) of
{ok,Message}-> gen_tcp:send(Client_socket,Message),
%% code not yet implemented here
client_loop(Client_socket);
{error,Why}-> io:fwrite("Error: ~s~n",[Why]),
gen_tcp:close(Client_socket)
end.
Comment: It is not the right place to store the Client list, because you will have to manage the client who are dying, either with links or monitor, so you need a receive block, incompatible with the socket listening. So I think that you should add a server to manage this list, which role is to listen the messages sent each time a new Client is launched, monitor the Clients, answer to the admin when he want to know the Client list ...
Here's a suggestion:
loop(Listening_socket, ClientList)->
case gen_tcp:accept(Listening_socket) of
{ok,Client_socket} ->
gen_tcp:send(Client_socket, "Hello, what is your name?"),
{_,Name} = gen_tcp:recv(Client_socket,0),
gen_tcp:send(Client_socket, "Hello, "),
gen_tcp:send(Client_socket, Name),
io:fwrite([Name]),
spawn(fun()-> client_loop(Client_socket) end),
loop(Listening_socket, [Client_socket | ClientList]);
{error,Why}->io:fwrite("Error: "),
io:fwrite([Why])
end.
A better solution would be to have a state record where you store all the vars you need (in this case, Listening_socket and ClientList) and loop with that state.
Related
I want to code and creat a bot for telegram that does these things:
1 - shows a massage to the person that hit start button
2 - then it gets a name as an input
3 - then again shows a massage
4 - getting an input
5 - at the end add the inputs to a defualt text and showing it;
for exampele:
-start
+Hi What is your name?
-X
+How old are you?
-Y
+Your name is X and you are Y years old.
My second Question is that how can I Connect to bots together, for example imagine I want to pass some input from this bot to make a poll(voting massage), in order to do that I should send the name to let's say #vote, how is that possible and what should I learn to do such things with my bot?
First you're gonna have to explore telegram bot API documentation here.
Then you should choose your programming language and the library you want to use.
There are different libraries for each language, I'm gonna name a few:
Go: https://github.com/aliforever/go-telegram-bot-api (DISCLAIMER: I wrote and maintain it)
Python: https://github.com/eternnoir/pyTelegramBotAPI
NodeJS: https://github.com/telegraf/telegraf
I'm gonna give you an example for what you want in python using pyTelegramBotAPI:
First install the library using pip:
pip install git+https://github.com/eternnoir/pyTelegramBotAPI.git
Then run this script:
import telebot
API_TOKEN = 'PLACE_BOT_TOKEN_HERE'
bot = telebot.TeleBot(API_TOKEN)
user_info = {}
def set_user_state(user_id, state):
if user_id not in user_info:
user_info[user_id] = {}
user_info[user_id]["state"] = state
def get_user_state(user_id):
if user_id in user_info:
if "state" in user_info[user_id]:
return user_info[user_id]["state"]
return "Welcome"
def set_user_info(user_id, name=None, age=None):
if name is None and age is None:
return
if name is not None:
user_info[user_id]["name"] = name
if age is not None:
user_info[user_id]["age"] = age
def get_user_info(user_id):
return user_info[user_id]
#bot.message_handler()
def echo_all(message):
user_id = message.from_user.id
if message.text == "/start":
bot.reply_to(message, "Hi What is your name?")
set_user_state(user_id, "EnterName")
return
user_state = get_user_state(user_id)
if user_state == "EnterName":
set_user_info(user_id, name=message.text)
bot.reply_to(message, "How old are you?")
set_user_state(user_id, "EnterAge")
return
if user_state == "EnterAge":
set_user_info(user_id, age=message.text)
info = get_user_info(user_id)
bot.reply_to(message, "Your name is %s and you are %s years old." %(info["name"], info["age"]))
set_user_state(user_id, "Welcome")
return
bot.reply_to(message, "To restart please send /start")
bot.infinity_polling()
Here we use a dictionary to place user state and info, you can place them anywhere like databases or json files.
Then we update a user's state based on their interactions with the bot.
For your second question, bots cannot communicate with each other so you should look for other solutions. In the case of your question where you want to create a poll, you should check sendPoll method as well as PollAnswer object which you receive when a user votes in a poll.
test.data <- data.frame(summary = c("Execute commands as root via buffer overflow in Tooltalk database server (rpc.ttdbserverd)."
,"Information from SSL-encrypted sessions via PKCS #1."
,"ip_input.c in BSD-derived TCP/IP implementations allows remote attackers to cause a denial of service (crash or hang) via crafted packets."),
wascname=c(NA, NA, "Improper Input Handling"),stringsAsFactors = FALSE)
wascNames <- data.frame(wascname=c("Abuse of Functionality","Brute Force","Buffer Overflow","Content Spoofing"
,"Credential/Session Prediction","Cross-Site Scripting","Cross-Site Request Forgery","Denial of Service"
,"Fingerprinting","Format String","HTTP Response Smuggling","HTTP Response Splitting"
,"HTTP Request Smuggling","HTTP Request Splitting","Integer Overflows","LDAP Injection"
,"Mail Command Injection","Null Byte Injection","OS Commanding","Path Traversal"
,"Predictable Resource Location","Remote File Inclusion (RFI)","Routing Detour","Session Fixation"
,"SOAP Array Abuse","SSI Injection","SQL Injection","URL Redirector Abuse"
,"XPath Injection","XML Attribute Blowup","XML External Entities","XML Entity Expansion"
,"XML Injection","XQuery Injection","Cross-site Scripting","Directory Indexing"
,"Improper Filesystem Permissions","Improper Input Handling","Improper Output Handling","Information Leakage"
,"Insecure Indexing","Insufficient Anti-Automation","Insufficient Authentication","Insufficient Authorization"
,"Insufficient Password Recovery","Insufficient Process Validation","Insufficient Session Expiration","Insufficient Transport Layer Protection"
,"Remote File Inclusion","URl Redirector Abuse"),stringsAsFactors = FALSE)
Below is the code I am have been trying to fix. If test.data$summary contains string in wascNames$wascname, replace test.data$wascname only if is.na:
test.data$wascname<-sapply(test.data$summary, function(x)
ifelse(identical(wascNames$wascname[str_detect(x,regex(wascNames$wascname, ignore_case = T))&
is.na(test.data$wascname)==TRUE], character(0)),test.data$wascname,
wascNames$wascname[str_detect(x,regex(wascNames$wascname, ignore_case = T))==TRUE]))
I want the following output:
Thank you in advance. Thought of using for loop, but would be too slow for 200000 obs.
I believe this should work:
test.data$wascname2 <- sapply(1:nrow(test.data), function(x) ifelse(is.na(test.data$wascname[x]),
wascNames$wascname[str_detect(test.data$summary[x], regex(wascNames$wascname, ignore_case = TRUE))],
test.data$wascname[x]))
test.data$wascname2
#[1] "Buffer Overflow" NA "Improper Input Handling"
It still loops with sapply, but I think that's unavoidable given your data structure (i.e. for each string, you want to look it up in your wascNames$wascname table).
I try to access to informations stored inside a Trovan reader using R serial package via a serial port. Connexion seems to be effective since the reader red led is shortly activated when serialConnection function is run but
read.serialConnection function give an empty string instead of the expected tag code. Have someone any ideas ? below a link to the reader documentation and the R script.
Many thanks
http://www.vantro.biz/GR-250%20Computer%20Interface%20Manual.pdf
trovan<-serialConnection(NA,port = "com1", mode = "9600,N,8,1",translation = 'cr', handshake = 'xonxoff')
open(trovan)
res<-read.serialConnection(trovan)
close(trovan)
res
[1] " "
library(serial)
library(radio)###have to add some waiting time between each step
trovan<-serialConnection("get_rfid", port = "COM4", mode ="9600,N,8,1", newline = 1, translation = "cr", handshake = "xonxoff") ##windows os
open(trovan)
wait(1)
write.serialConnection(trovan,"N")
wait(2.5)
res<-read.serialConnection(trovan)
close(trovan)
Is it possible to make http GET requests from within a node-red "function" node.
If yes could somebody point me to some example code please.
The problem I want to solve is the following:
I want to parse a msg.payload with custom commands. For each command I want to make an http request and replace the command with the response of a HTTP GET request.
expl:
msg.payload = "Good day %name%. It's %Time% in the %TimeOfDay%. Time for your coffee";
The %name%,%TimeOfDay% and %Time% should be replaced by the content of a Get request to http://nodeserver/name,..., http://nodeserver/Time.
thnx Hardilb,
After half a day searching I found out that the http-node can also be configured by placing a node just before it setting the
msg.url = "http://127.0.0.1:1880/" + msg.command ;
msg.method = "GET";
I used the following code to get a list of commands
var parts = msg.payload.split('%'),
len = parts.length,
odd = function(num){return num % 2;};
msg.txt= msg.payload;
msg.commands = [];
msg.nrOfCommands = 0;
for (var i = 0; i < len ; i++){
if(odd(i)){
msg.commands.push(parts[i]);
msg.nrOfCommands = msg.nrOfCommands + 1;
}
}
return msg;
You should avoid doing asynchronous or blocking stuff in function nodes.
Don't try to do it all in one function node, chain multiple function nodes with multiple http Request nodes to build the string up a part at a time.
You can do this by stashing the string in another variable off the msg object instead of payload.
One thing to looks out for is that you should make sure you clear out msg.headers before each call to the next http Request node
I have successfully managed to implement the sendmailR function to send one message to one recipient.
Do you know if it is possible to send that same message to multiple recipients within the function? A form of CC'ing?
If not I think the only way is to loop round on a variable, which would normally be okay but for my current code would result with a loop within a loop and make things fairly and hopefully unnecessary complex
I cant see anything in the documentation that would appear to indicate functionality like this --> http://cran.r-project.org/web/packages/sendmailR/sendmailR.pdf
Thanks for any help, I will keep testing to see if there is a work around inm the meantime!
In the source code for sendmail it states...
if (length(to) != 1)
stop("'to' must be a single address.")
So this leaves you with several options (all of which are loops).The execution time of a loop compared to sending the email will be negligible. A couple of options are:
Option 1
Use Vectorize to vectorise the to argument of sendmail, allowing you to supply a character vector of email addresses to send to...
sendmailV <- Vectorize( sendmail , vectorize.args = "to" )
emails <- c( "me#thisis.me.co.uk" , "you#whereami.org" )
sendmailV( from = "me#me.org" , to = emails )
Option 2
Using sapply to iterate over the a character vector of email addresses applying the sendmail function each time...
sapply( emails , function(x) sendmail( to = "me#me.org" , to = x ) )
You could try the development version of the mailR package available on github https://github.com/rpremraj/mailR
Using mailR, you could send an email in HTML format as below:
send.mail(from = "sender#gmail.com",
to = c("recipient1#gmail.com", "recipient2#gmail.com"),
cc = c("CCrecipient1#gmail.com", "CCrecipient2#gmail.com"),
subject = "Subject of the email",
body = "<html>The apache logo - <img src=\"http://www.apache.org/images/asf_logo_wide.gif\"></html>",
html = TRUE,
smtp = list(host.name = "smtp.gmail.com", port = 465, user.name = "gmail_username", passwd = "password", ssl = TRUE),
authenticate = TRUE,
send = TRUE)
This does the trick for me:
Define from, msg, subject, body seperatly:
from <- sprintf("<sendmailR#%s>", Sys.info()[4])
.....
TO <- c("<adres1#domain.com>", "<adres2#domain.com>")
sapply(TO, function(x) sendmail(from, to = x, subject, msg, body))