Could anyone tell how to set proxy configuration with funciton aleph.http/websocket-client of
clj-commons/aleph "0.4.7-alpha7"
Here is my code:
(def proxy-config
{:connection-options {:proxy-options {:host "127.0.0.1"
:port 7890
:protocol :socks5}}})
(defn create-connection [url proxy-config]
(try
(let [conn #(aleph.http/websocket-client url proxy-config)]
(info "websocket connection established, url:" url ".")
conn)
(catch Exception e
(error "websocket connection established failed, url:" url "." e))))
Related
I am using Julia's SimpleWebSockets to open a websocket connection. I want it to reconnect after any disconnects. Something is wrong with the notify commented below, it doesnt run after disconnect, thereby preventing the rest of the code from continuing.
using SimpleWebsockets
function connect_loop(C::Coinbase, msg_channel::Channel)
while true
client = WebsocketClient()
ended = Condition()
listen(client, :connect) do ws
listen(ws, :message) do message
put!(msg_channel, message)
end
listen(ws, :error) do reason
#warn "Websocket connection error" reason...
notify(ended)
end
listen(ws, :close) do reason
#warn "Websocket connection closed" reason...
notify(ended)
end
# for msg in C.command_channel
# send(ws, JSON.json(msg))
# end
end
listen(C.client, :connectError) do err
println("Websocket Connect Error.")
notify(ended) # This is not working !!!!!!!!!
end
println("connecting")
#async open(C.client, "wss://ws-feed.pro.coinbase.com")
println("wait for ended")
wait(ended)
println("ended")
sleep(2)
end
end
Procedure is to connect on Wifi, then after successful connection disable the wifi and we should see it go into a reconnect loop, but instead it just stalls waiting on that notify call.
connecting
wait for ended
┌ Warning: Websocket connection closed
│ code = 1006
│ description = "could not ping the server."
└ # Main ~/src/tibra/Tibra.jl/src/MarketDataIO/Coinbase.jl:60
ended
connecting
wait for ended
Websocket Connect Error.
I want to make slack bot.
I can not solve this error.
(ql:quickload '(:cl-slack
:event-emitter
:websocket-driver
:jonathan
:cl-async
)
:silent t)
(defconstant +token+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
(defconstant +channel+ "xxx")
(defvar *client* (make-instance 'cl-slack.core:slack-client
:token +token+))
(let ((url (getf (jonathan:parse (cl-slack.rtm:start *client* nil)) :|url|)))
(format t url)
(defparameter *slack-bot* (wsd:make-client url)))
(defun params (id type channel text)
(jonathan:to-json (list :|id| id
:|type| type
:|channel| channel
:|text| text)))
(wsd:on :message *slack-bot*
(lambda (message)
(let ((data (jonathan:parse message)))
(format t "~A~%" data)
(when (string= (getf data :|type|) "message")
(wsd:send *slack-bot*
(params 1
"message"
(getf data :|channel|)
(getf data :|text|)))))))
(as:with-event-loop (:catch-app-errors t)
(wsd:start-connection *slack-bot*))
error is
[20:42:25] cl-async-util - handle-error: SSL verify error: 20 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
I'm using the Sente library for communicating over websockets. The communication is already working but the session seem to be missing. I'm setting up Sente like this:
;; According to https://github.com/ptaoussanis/sente
(let [{:keys [ch-recv send-fn connected-uids
ajax-post-fn ajax-get-or-ws-handshake-fn]}
(sente/make-channel-socket! (get-sch-adapter) {})]
(def ring-ajax-post ajax-post-fn)
(def ring-ajax-get-or-ws-handshake ajax-get-or-ws-handshake-fn)
(def ch-chsk ch-recv) ; ChannelSocket's receive channel
(def chsk-send! send-fn) ; ChannelSocket's send API fn
(def connected-uids connected-uids)) ; Watchable, read-only atom
(defmulti handle-message
"Multimethod to handle messages coming from the clients"
:id)
(defmethod handle-message
:default
[{:as ev-msg :keys [event id ?data ring-req ?reply-fn send-fn]}]
(let [session (:session ring-req)
uid (:uid session)]
(printf "Ring request: %s\n" ring-req)
(printf "Session: %s\n" session)
(printf "UID: %s\n" uid)
(printf "Unhandled event: %s\n" event)
(printf "Thread id: %s\n" (.getId (Thread/currentThread)))
(flush)
(when ?reply-fn
(?reply-fn {:umatched-event-as-echoed-from-from-server event}))))
(defmethod handle-message :chsk/ws-ping [arg]
(println "ping")) ; Ignore pings
(mount/defstate ^{:on-reload :noop}
socket-server
:start (sente/start-server-chsk-router!
ch-chsk
(fn [arg]
(handle-message arg)
(println "\n"))
#_{:simple-auto-threading? true})
:stop (socket-server))
When I send a message from the client, which is authenticated, I get this output:
Ring request: {:identity nil, :cookies {"ring-session" {:value "8df3a322-313a-4f16-873c-9ea7275af723"}}, :remote-addr "0:0:0:0:0:0:0:1", :params {:client-id "7a2d8913-ad69-4c82-83ed-30ffb1e3c50a"}, :flash nil, :route-params {}, :headers {"origin" "file://", "host" "localhost:3000", "upgrade" "websocket", "user-agent" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) projectx/0.1.0 Chrome/52.0.2743.82 Electron/1.3.3 Safari/537.36", "cookie" "ring-session=8df3a322-313a-4f16-873c-9ea7275af723", "connection" "Upgrade", "pragma" "no-cache", "sec-websocket-key" "g9lEvc59vyaE6RLbM36iyQ==", "accept-language" "en-US", "sec-websocket-version" "13", "accept-encoding" "gzip, deflate", "sec-websocket-extensions" "permessage-deflate; client_max_window_bits", "cache-control" "no-cache"}, :async-channel #object[org.httpkit.server.AsyncChannel 0x8958245 "/0:0:0:0:0:0:0:1:3000<->/0:0:0:0:0:0:0:1:64374"], :server-port 3000, :content-length 0, :form-params {}, :compojure/route [:get "/web-socket"], :websocket? true, :session/key nil, :query-params {"client-id" "7a2d8913-ad69-4c82-83ed-30ffb1e3c50a"}, :content-type nil, :character-encoding "utf8", :uri "/web-socket", :server-name "localhost", :query-string "client-id=7a2d8913-ad69-4c82-83ed-30ffb1e3c50a", :body nil, :multipart-params {}, :scheme :http, :request-method :get, :session {}}
Session: {}
UID: null
Unhandled event: [:projectx.core/boo "boo!"]
Thread id: 38
The handlers are quite simple and are set up like this:
(def app-routes
(routes
(GET "/web-socket" req (socket/ring-ajax-get-or-ws-handshake req))
(POST "/web-socket" req (socket/ring-ajax-post req))
#'service-routes
(route/not-found
"page not found")))
(defn app [] (middleware/wrap-base #'app-routes))
middleware/wrap-base contains the session handling and it looks like this:
(defn wrap-identity [handler]
(fn [request]
(println (:cookies request))
(if-let [current-user-id (get-in request [:session :identity])]
(if-let [current-user (when current-user-id (db/get-user-by-id {:id current-user-id}))]
(handler (assoc request :current-user current-user))
(handler (-> request
(dissoc :identity)
(dissoc-in [:session :identity])))))
(handler request))))
(defn wrap-auth [handler]
(let [backend (session-backend)]
(-> handler
wrap-identity
(wrap-authentication backend)
(wrap-authorization backend))))
(defn wrap-base [handler]
(-> ((:middleware defaults) handler)
wrap-auth
(wrap-defaults
(-> site-defaults
(assoc-in [:params :keywordize] true) ; Needed by Sente: https://github.com/ptaoussanis/sente#on-the-server-clojure-side
(assoc-in [:params :urlencoded] true) ; Needed by Sente: https://github.com/ptaoussanis/sente#on-the-server-clojure-side
(assoc-in [:security :anti-forgery] false)
(assoc-in [:session :store] (ttl-memory-store (* 60 30)))))))
This is working just fine for the AJAX requests. I even tried setting :uid in the session as well as starting the channel in the client after the user logged in, and nothing changed the fact that the session remained empty.
The problem was on the client side. The connection has to be established after the user logged in for that session to appear in the socket. I was following the code example that looks like this:
;; https://github.com/ptaoussanis/sente
(let [{:keys [chsk ch-recv send-fn state]}
(sente/make-channel-socket! "/web-socket"
{:host conf/remote-host:port
:protocol (str conf/remote-protocol ":")
:type :auto})]
(def chsk chsk)
(def ch-chsk ch-recv) ; ChannelSocket's receive channel
(def chsk-send! send-fn) ; ChannelSocket's send API fn
(def chsk-state state)) ; Watchable, read-only atom
(defonce router_ (atom nil))
(defn stop-router! [] (when-let [stop-f #router_] (stop-f)))
(defn start-router! []
(stop-router!)
(reset! router_
(sente/start-client-chsk-router!
ch-chsk (fn [{:keys [ch-recv send-fn state event id ?data] :as arg}]
(println "Event" event)))))
with the misunderstanding that calling start-router was going to establish the communication but instead it's established as soon as make-channel-socket! is called; so, it shouldn't be called until the session is ready.
like in client sockets
socket = Socket.new(AF_INET, SOCK_STREAM, 0)
sockaddr = Socket.pack_sockaddr_in(2200, 'localhost')
socket.connect_nonblock(sockaddr)
server_msg = socket.recv_nonblock(3058)
vs
clientSession = TCPSocket.new( "localhost",2200)
server_msg = socket.recv(3058)
like in server
socket = Socket.new(AF_INET, SOCK_STREAM, 0)
sockaddr = Socket.sockaddr_in(6212, 'localhost')
socket.bind(sockaddr)
socket.listen(5)
vs
server = TCPServer.new("localhost",3000)
Is it syntactically both different or logically we should make them non-blocking?
Maybe you could use timeouts?
We use the following code for ruby socket clients to time out if there is no response:
#socket = TCPSocket.new(host, port)
timeout=30.0
ready = IO.select([#socket], nil, nil, timeout)
if ready
response = #socket.recv(SOCKET_READ_SIZE)
else
message = "Socket communications timed out after #{timeout} seconds"
logger.error message
#socket.close if #socket.present?
raise message
end
I asked a question about signal on windows with the same code,here is another question
import IO
import Control.Exception hiding (catch)
import Control.Concurrent
import Network
main = withSocketsDo $ do {main'}
main' = listenOn (PortNumber 9900) >>= acceptConnections
acceptConnections sock = do
putStrLn $ "trying to accept" ++ (show sock)-- debug msg
conn#(h,host,port) <- accept sock
print conn -- debug msg
forkIO $ catch (talk conn `finally` hClose h) (\e -> print e)
acceptConnections sock
talk conn#(h,_,_) = hGetLine h >>= hPutStrLn h >> hFlush h >> talk conn
I run the program on win7,and it looks like the socket created succeed,but I can't telnet on,and netstat doesn't show any listening socket with the process,is there anything wrong?Or,haskell has bug on windows?(By the way,on debian with this code works perfect)
when I use netstat -a on win7,I found the listening ip with port 9900 is [::],neither is 127.0.0.1 nor 0.0.0.0,so I guess the problem is during create socket in function "listenOn",then I wrote "listenOn2" replaced.And the problem is solved.
Here is the full code:(the only difference is change the proto from [[getProtocolNumber "tcp"]] to [[defaultProtocol]]),maybe this is a bug.
import IO
import Control.Exception hiding (catch)
import Control.Concurrent
import Network
import Network.Socket
listenOn2 (PortNumber port) = do
--proto <- getProtocolNumber "tcp" ,here is the difference!!!!
let proto = defaultProtocol
bracketOnError
(socket AF_INET Stream proto)
(sClose)
(\sock -> do
setSocketOption sock ReuseAddr 1
--addr <- inet_addr "127.0.0.1"
bindSocket sock (SockAddrInet port iNADDR_ANY)
listen sock maxListenQueue
return sock
)
main = withSocketsDo $ do {main'}
main' = listenOn2 (PortNumber 9900) >>= acceptConnections
acceptConnections sock = do
putStrLn $ "trying to accept" ++ (show sock)-- debug msg
conn#(h,host,port) <- Network.accept sock
print conn -- debug msg
forkIO $ catch (talk conn `finally` hClose h) (\e -> print e)
acceptConnections sock
talk conn#(h,_,_) = hGetLine h >>= hPutStrLn h >> hFlush h >> talk conn