I have a problem with making a call using the PJSUA2 api for python, and that is that when receiving the 407 authorization request is not responded to from PJSIP.
Eventhough it says that the request is begin sent in the console from PJSIP, it doesnt actually sent anything when looking at it with Wireshark.
I have no warnings or errors indicating something going wrong. The log is filled with PJSIP trying to make the INVITE request with authorization but doesn't get a response because it probably isn't actually sent.
What is happening and how can I fix it?
The 407 response:
13:01:03.043 tsx0x1fd1228 ....Temporary failure in sending Request msg INVITE/cseq=21903 (tdta0x1fce0a8), will try next server: Unsupported transport (PJSIP_EUNSUPTRANSPORT)
13:01:03.043 pjsua_core.c ....TX 1427 bytes Request msg INVITE/cseq=21903 (tdta0x1fce0a8) to UDP 192.168.2.16:5080:
INVITE sip:+316xxxxxxxx#192.168.2.16:5080 SIP/2.0
Via: SIP/2.0/UDP 192.168.2.11:57880;rport;branch=z9hG4bKPj1cd4c855-e407-4620-af0b-d245aeab2132
Max-Forwards: 70
From: <sip:1010#192.168.2.16>;tag=e7cf4af1-bb8e-4d59-8d79-5050118e9bd5
To: <sip:+316xxxxxxxx#192.168.2.16>
Contact: <sip:1010#192.168.2.11:57880;ob>
Call-ID: 7c17cb03-7833-4a0d-95be-1085ab6ce2ff
CSeq: 21903 INVITE
Allow: PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, INFO, SUBSCRIBE, NOTIFY, REFER, MESSAGE, OPTIONS
Supported: replaces, 100rel, timer, norefersub
Session-Expires: 1800
Min-SE: 90
Content-Type: application/sdp
Content-Length: 806
v=0
o=- 3884587263 3884587263 IN IP4 172.22.178.52
s=pjmedia
b=AS:117
t=0 0
a=X-nat:0
m=audio 4000 RTP/AVP 8 0 9 96 97 98 99 3 100 101 102 120 121 122 123
c=IN IP4 172.22.178.52
b=TIAS:96000
a=rtcp:4001 IN IP4 172.22.178.52
a=sendrecv
a=rtpmap:8 PCMA/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:9 G722/8000
a=rtpmap:96 iLBC/8000
a=fmtp:96 mode=30
a=rtpmap:97 speex/8000
a=rtpmap:98 speex/16000
a=rtpmap:99 speex/32000
a=rtpmap:3 GSM/8000
a=rtpmap:100 AMR/8000
a=rtpmap:101 AMR-WB/16000
a=rtpmap:102 opus/48000/2
a=fmtp:102 useinbandfec=1
a=rtpmap:120 telephone-event/8000
a=fmtp:120 0-16
a=rtpmap:121 telephone-event/16000
a=fmtp:121 0-16
a=rtpmap:122 telephone-event/32000
a=fmtp:122 0-16
a=rtpmap:123 telephone-event/48000
a=fmtp:123 0-16
a=ssrc:1026369925 cname:0a2ee5815d3913eb
--end msg--
13:01:03.057 pjsua_core.c .RX 693 bytes Response msg 407/INVITE/cseq=21903 (rdata0x1fa9088) from UDP 192.168.2.16:5080:
SIP/2.0 407 Proxy Authentication Required
Via: SIP/2.0/UDP 192.168.2.11:57880;rport=57880;branch=z9hG4bKPj1cd4c855-e407-4620-af0b-d245aeab2132
From: <sip:1010#192.168.2.16>;tag=e7cf4af1-bb8e-4d59-8d79-5050118e9bd5
To: <sip:+316xxxxxxxx#192.168.2.16>;tag=4SXQa24prg6rg
Call-ID: 7c17cb03-7833-4a0d-95be-1085ab6ce2ff
CSeq: 21903 INVITE
User-Agent: FreeSWITCH
Accept: application/sdp
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY
Supported: path, replaces
Allow-Events: talk, hold, conference, refer
Proxy-Authenticate: Digest realm="192.168.2.16", nonce="1e8bd613-7ac0-4516-bbeb-4778ef103ed7", algorithm=MD5, qop="auth"
Content-Length: 0
--end msg--
13:01:03.057 pjsua_core.c ..TX 375 bytes Request msg ACK/cseq=21903 (tdta0x7fdc68000c08) to UDP 192.168.2.16:5080:
ACK sip:+316xxxxxxxx#192.168.2.16:5080 SIP/2.0
Via: SIP/2.0/UDP 192.168.2.11:57880;rport;branch=z9hG4bKPj1cd4c855-e407-4620-af0b-d245aeab2132
Max-Forwards: 70
From: <sip:1010#192.168.2.16>;tag=e7cf4af1-bb8e-4d59-8d79-5050118e9bd5
To: <sip:+316xxxxxxxx#192.168.2.16>;tag=4SXQa24prg6rg
Call-ID: 7c17cb03-7833-4a0d-95be-1085ab6ce2ff
CSeq: 21903 ACK
Content-Length: 0
The "sent" request:
13:01:03.057 pjsua_core.c .......TX 1708 bytes Request msg INVITE/cseq=21904 (tdta0x1fce0a8) to UDP 192.168.2.16:5080:
INVITE sip:+316xxxxxxxx#192.168.2.16:5080 SIP/2.0
Via: SIP/2.0/UDP 192.168.2.11:57880;rport;branch=z9hG4bKPjbd8dbeef-81d0-4f0d-9e07-8e1526c3109f
Max-Forwards: 70
From: <sip:1010#192.168.2.16>;tag=e7cf4af1-bb8e-4d59-8d79-5050118e9bd5
To: <sip:+316xxxxxxxx#192.168.2.16>
Contact: <sip:1010#192.168.2.11:57880;ob>
Call-ID: 7c17cb03-7833-4a0d-95be-1085ab6ce2ff
CSeq: 21904 INVITE
Allow: PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, INFO, SUBSCRIBE, NOTIFY, REFER, MESSAGE, OPTIONS
Supported: replaces, 100rel, timer, norefersub
Session-Expires: 1800
Min-SE: 90
Proxy-Authorization: Digest username="1010", realm="192.168.2.16", nonce="1e8bd613-7ac0-4516-bbeb-4778ef103ed7", uri="sip:+316xxxxxxxx#192.168.2.16:5080", response="4e640a090416645a11c6a6198fe4d523", algorithm=MD5, cnonce="5b5c5283ae234889ba31abc34b7f0a4e", qop=auth, nc=00000001
Content-Type: application/sdp
Content-Length: 806
v=0
o=- 3884587263 3884587263 IN IP4 172.22.178.52
s=pjmedia
b=AS:117
t=0 0
a=X-nat:0
m=audio 4000 RTP/AVP 8 0 9 96 97 98 99 3 100 101 102 120 121 122 123
c=IN IP4 172.22.178.52
b=TIAS:96000
a=rtcp:4001 IN IP4 172.22.178.52
a=sendrecv
a=rtpmap:8 PCMA/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:9 G722/8000
a=rtpmap:96 iLBC/8000
a=fmtp:96 mode=30
a=rtpmap:97 speex/8000
a=rtpmap:98 speex/16000
a=rtpmap:99 speex/32000
a=rtpmap:3 GSM/8000
a=rtpmap:100 AMR/8000
a=rtpmap:101 AMR-WB/16000
a=rtpmap:102 opus/48000/2
a=fmtp:102 useinbandfec=1
a=rtpmap:120 telephone-event/8000
a=fmtp:120 0-16
a=rtpmap:121 telephone-event/16000
a=fmtp:121 0-16
a=rtpmap:122 telephone-event/32000
a=fmtp:122 0-16
a=rtpmap:123 telephone-event/48000
a=fmtp:123 0-16
a=ssrc:1026369925 cname:0a2ee5815d3913eb
The flow sequence:
Wireshark flow sequence
Related
I'm trying to write a simple SIP agent to receive a call using PJSUA2 python swig module, but can't see how this swig module works. I've got the following code
import pjsua2 as pj
import time
class Endpoint(pj.Endpoint):
"""
This is high level Python object inherited from pj.Endpoint
"""
instance = None
def __init__(self):
pj.Endpoint.__init__(self)
Endpoint.instance = self
def validateUri(uri):
return Endpoint.instance.utilVerifyUri(uri) == pj.PJ_SUCCESS
def validateSipUri(uri):
return Endpoint.instance.utilVerifySipUri(uri) == pj.PJ_SUCCESS
# Call class
class Call(pj.Call):
"""
High level Python Call object, derived from pjsua2's Call object.
"""
def __init__(self, acc, peer_uri='', call_id=pj.PJSUA_INVALID_ID):
pj.Call.__init__(self, acc, call_id)
self.acc = acc
self.peerUri = peer_uri
self.connected = False
self.onhold = False
def onCallState(self, prm):
ci = self.getInfo()
self.connected = ci.state == pj.PJSIP_INV_STATE_CONFIRMED
def onCallMediaState(self, prm):
ci = self.getInfo()
for mi in ci.media:
if mi.type == pj.PJMEDIA_TYPE_AUDIO and \
(mi.status == pj.PJSUA_CALL_MEDIA_ACTIVE or
mi.status == pj.PJSUA_CALL_MEDIA_REMOTE_HOLD):
m = self.getMedia(mi.index)
am = pj.AudioMedia.typecastFromMedia(m)
# connect ports
Endpoint.instance.audDevManager().getCaptureDevMedia().startTransmit(am)
am.startTransmit(Endpoint.instance.audDevManager().getPlaybackDevMedia())
if mi.status == pj.PJSUA_CALL_MEDIA_REMOTE_HOLD and not self.onhold:
print("'%s' sets call onhold" % self.peerUri)
self.onhold = True
elif mi.status == pj.PJSUA_CALL_MEDIA_ACTIVE and self.onhold:
print("'%s' sets call active" % self.peerUri)
self.onhold = False
def onDtmfDigit(self, prm):
# print("Got DTMF:" + prm.digit)
pass
def onCallMediaTransportState(self, prm):
# print("Media transport state")
pass
class Account(pj.Account):
def onRegState(self, prm):
print("***OnRegState: " + prm.reason)
def onMwiInfo(self, prm):
print("OnMwiState: " + prm.reason)
def onBuddyState(self, prm):
print("OnBuddyState: " + prm.reason)
def onIncommingSubscribe(self, prm):
print("OnSubscribeState: " + prm.reason)
def OnIncomingCall(self, prm):
c = Call(self, call_id=prm.callId)
call_prm = pj.CallOpParam()
call_prm.statusCode = 180
c.answer(call_prm)
ci = c.getInfo()
if input(f"Accept call from {ci.remoteUri}?") == u'yes':
call_prm.statusCode = 200
c.answer(call_prm)
else:
c.hangup(call_prm)
def initalise_sip_stack():
ep_cfg = pj.EpConfig()
ep = Endpoint()
ep.libCreate()
ep.libInit(ep_cfg)
sip_tp_config = pj.TransportConfig()
sip_tp_config.port = 5060
ep.transportCreate(pj.PJSIP_TRANSPORT_UDP, sip_tp_config)
ep.libStart()
acfg = pj.AccountConfig()
acfg.idUri = "sip:056004#172.20.1.8"
acfg.regConfig.registrarUri = "sip:172.20.1.8"
creds = pj.AuthCredInfo("digest", "*", "056004", 0, "somepass")
acfg.sipConfig.authCreds.append(creds)
acc = Account()
acc.create(acfg)
return ep
if __name__ == "__main__":
endpoint = initalise_sip_stack()
time.sleep(600)
endpoint.libDestroy()
This little client is able to register in my asterisk server as you can see
raspberrypi*CLI> pjsip show contacts
Contact: <Aor/ContactUri..............................> <Hash....> <Status> <RTT(ms)..>
==========================================================================================
Contact: 056003/sip:056003#172.20.1.13:5060 058bca1427 Avail 41.057
Contact: 056004/sip:056004#172.20.1.2:5060;ob e8ff0c4e2b Avail 2.358
Objects found: 2
However, when I place a call from 056003 contact, I can see the following trace from pjsua2:
16:52:37.918 pjsua_core.c .RX 947 bytes Request msg INVITE/cseq=23923 (rdata0x7f5f6c001c48) from UDP 172.20.1.8:5060:
INVITE sip:056004#172.20.1.2:5060;ob SIP/2.0
Via: SIP/2.0/UDP 0.0.0.0:5060;rport;branch=z9hG4bKPjada6202d-813b-499c-9b5c-2ad5abf6706e
From: "MI 3" <sip:056003#172.20.1.8>;tag=91efaf53-e6fb-45dc-b2d4-ddc99a6c3c36
To: <sip:056004#172.20.1.2;ob>
Contact: <sip:056003#0.0.0.0:5060>
Call-ID: 1bf35bec-1a88-468e-bd17-dfa99086c457
CSeq: 23923 INVITE
Allow: OPTIONS, REGISTER, SUBSCRIBE, NOTIFY, PUBLISH, INVITE, ACK, BYE, CANCEL, UPDATE, PRACK, MESSAGE, REFER
Supported: 100rel, timer, replaces, norefersub, histinfo
Session-Expires: 1800
Min-SE: 90
P-Asserted-Identity: "MI 3" <sip:056003#172.20.1.8>
Max-Forwards: 70
User-Agent: FPBX-15.0.23(16.16.1)
Content-Type: application/sdp
Content-Length: 231
v=0
o=- 519853527 519853527 IN IP4 172.20.1.8
s=Asterisk
c=IN IP4 172.20.1.8
t=0 0
m=audio 14490 RTP/AVP 9 101
a=rtpmap:9 G722/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
a=ptime:20
a=maxptime:150
a=sendrecv
--end msg--
16:52:37.918 pjsua_call.c .Incoming Request msg INVITE/cseq=23923 (rdata0x7f5f6c001c48)
16:52:37.919 pjsua_acc.c ..No available account to handle Request msg INVITE/cseq=23923 (rdata0x7f5f6c001c48)
16:52:37.919 pjsua_core.c ..TX 402 bytes Response msg 480/INVITE/cseq=23923 (tdta0x7f5f6c006b78) to UDP 172.20.1.8:5060:
SIP/2.0 480 Temporarily Unavailable
Via: SIP/2.0/UDP 0.0.0.0:5060;rport=5060;received=172.20.1.8;branch=z9hG4bKPjada6202d-813b-499c-9b5c-2ad5abf6706e
Call-ID: 1bf35bec-1a88-468e-bd17-dfa99086c457
From: "MI 3" <sip:056003#172.20.1.8>;tag=91efaf53-e6fb-45dc-b2d4-ddc99a6c3c36
To: <sip:056004#172.20.1.2;ob>;tag=z9hG4bKPjada6202d-813b-499c-9b5c-2ad5abf6706e
CSeq: 23923 INVITE
Content-Length: 0
--end msg--
16:52:37.919 pjsua_call.c ..Unable to accept incoming call (no available account)
16:52:37.921 pjsua_core.c .RX 433 bytes Request msg ACK/cseq=23923 (rdata0x7f5f6c001c48) from UDP 172.20.1.8:5060:
ACK sip:056004#172.20.1.2:5060;ob SIP/2.0
Via: SIP/2.0/UDP 0.0.0.0:5060;rport;branch=z9hG4bKPjada6202d-813b-499c-9b5c-2ad5abf6706e
From: "MI 3" <sip:056003#172.20.1.8>;tag=91efaf53-e6fb-45dc-b2d4-ddc99a6c3c36
To: <sip:056004#172.20.1.2;ob>;tag=z9hG4bKPjada6202d-813b-499c-9b5c-2ad5abf6706e
Call-ID: 1bf35bec-1a88-468e-bd17-dfa99086c457
CSeq: 23923 ACK
Max-Forwards: 70
User-Agent: FPBX-15.0.23(16.16.1)
Content-Length: 0
--end msg--
16:52:41.382 pjsua_core.c .RX 419 bytes Request msg OPTIONS/cseq=9130 (rdata0x7f5f6c001c48) from UDP 172.20.1.8:5060:
OPTIONS sip:056004#172.20.1.2:5060;ob SIP/2.0
Via: SIP/2.0/UDP 0.0.0.0:5060;rport;branch=z9hG4bKPj54cf9751-5357-4887-91d3-b8d97ea6d2f4
From: <sip:056004#172.20.1.8>;tag=9a799201-1424-418d-b5c4-44997fc40829
To: <sip:056004#172.20.1.2;ob>
Contact: <sip:056004#0.0.0.0:5060>
Call-ID: 84c421ff-ae98-475f-b11e-ac7cd27caa66
CSeq: 9130 OPTIONS
Max-Forwards: 70
User-Agent: FPBX-15.0.23(16.16.1)
Content-Length: 0
--end msg--
16:52:41.382 pjsua_core.c .TX 760 bytes Response msg 200/OPTIONS/cseq=9130 (tdta0x7f5f6c003c18) to UDP 172.20.1.8:5060:
SIP/2.0 200 OK
Via: SIP/2.0/UDP 0.0.0.0:5060;rport=5060;received=172.20.1.8;branch=z9hG4bKPj54cf9751-5357-4887-91d3-b8d97ea6d2f4
Call-ID: 84c421ff-ae98-475f-b11e-ac7cd27caa66
From: <sip:056004#172.20.1.8>;tag=9a799201-1424-418d-b5c4-44997fc40829
To: <sip:056004#172.20.1.2;ob>;tag=z9hG4bKPj54cf9751-5357-4887-91d3-b8d97ea6d2f4
CSeq: 9130 OPTIONS
Allow: PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, INFO, SUBSCRIBE, NOTIFY, REFER, MESSAGE, OPTIONS
Accept: application/sdp, application/pidf+xml, application/xpidf+xml, application/simple-message-summary, message/sipfrag;version=2.0, application/im-iscomposing+xml, text/plain
Supported: replaces, 100rel, timer, norefersub, trickle-ice
Allow-Events: presence, message-summary, refer
Content-Length: 0
--end msg--
And not sure why it says pjsua_acc.c ..No available account to handle Request msg INVITE/cseq=23923 (rdata0x7f5f6c001c48)
Some idea? what part is bad implemented in my code? Maybe should I handle the initalise_sip_stack() function as a thread/process?
Thank you very much!
How can I find out what number is assigned to a specific value in any parameter in the IP Protocol or any other Protocol?
If I set a value:
a=IP(proto=73)
I get:
version= 4
ihl= None
tos= 0x0
len= None
id= 1
flags=
frag= 0
ttl= 64
**proto= rspf**
chksum= None
src= 127.0.0.1
dst= 127.0.0.1
\options\
If I set another value:
a=IP(proto=12)
I get:
version= 4
ihl= None
tos= 0x0
len= None
id= 1
flags=
frag= 0
ttl= 64
proto= pup
chksum= None
src= 127.0.0.1
dst= 127.0.0.1
\options\
and so on.
Some number is assigned to a value in some parameter of the package. At the moment, I'm listing every number from 1 to 100 to see what's hidden there, but it's a very long and painful process.
How to see which numbers are assigned to values?
Thanks.
scapy loads the protocol list from your system
definition of the proto field in scapy:
https://github.com/secdev/scapy/blob/master/scapy/layers/inet.py#L466
it is define as:
ByteEnumField("proto", 0, IP_PROTOS),
definition of IP_PROTOS:
https://github.com/secdev/scapy/blob/bfd9c52af61978ac872d3c0bf5eef81168d88ca9/scapy/data.py#L476
for win:
IP_PROTOS = load_protocols(os.environ["SystemRoot"] + "\\system32\\drivers\\etc\\protocol") # noqa: E501
for linux:
IP_PROTOS = load_protocols("/etc/protocols")
now, I have linux system, so for me it looks like that:
cat /etc/protocols
# Internet (IP) protocols
#
# Updated from http://www.iana.org/assignments/protocol-numbers and other
# sources.
# New protocols will be added on request if they have been officially
# assigned by IANA and are not historical.
# If you need a huge list of used numbers please install the nmap package.
ip 0 IP # internet protocol, pseudo protocol number
hopopt 0 HOPOPT # IPv6 Hop-by-Hop Option [RFC1883]
icmp 1 ICMP # internet control message protocol
igmp 2 IGMP # Internet Group Management
ggp 3 GGP # gateway-gateway protocol
ipencap 4 IP-ENCAP # IP encapsulated in IP (officially ``IP'')
st 5 ST # ST datagram mode
tcp 6 TCP # transmission control protocol
egp 8 EGP # exterior gateway protocol
igp 9 IGP # any private interior gateway (Cisco)
pup 12 PUP # PARC universal packet protocol
udp 17 UDP # user datagram protocol
hmp 20 HMP # host monitoring protocol
xns-idp 22 XNS-IDP # Xerox NS IDP
rdp 27 RDP # "reliable datagram" protocol
iso-tp4 29 ISO-TP4 # ISO Transport Protocol class 4 [RFC905]
dccp 33 DCCP # Datagram Congestion Control Prot. [RFC4340]
xtp 36 XTP # Xpress Transfer Protocol
ddp 37 DDP # Datagram Delivery Protocol
idpr-cmtp 38 IDPR-CMTP # IDPR Control Message Transport
ipv6 41 IPv6 # Internet Protocol, version 6
ipv6-route 43 IPv6-Route # Routing Header for IPv6
ipv6-frag 44 IPv6-Frag # Fragment Header for IPv6
idrp 45 IDRP # Inter-Domain Routing Protocol
rsvp 46 RSVP # Reservation Protocol
gre 47 GRE # General Routing Encapsulation
esp 50 IPSEC-ESP # Encap Security Payload [RFC2406]
ah 51 IPSEC-AH # Authentication Header [RFC2402]
skip 57 SKIP # SKIP
ipv6-icmp 58 IPv6-ICMP # ICMP for IPv6
ipv6-nonxt 59 IPv6-NoNxt # No Next Header for IPv6
ipv6-opts 60 IPv6-Opts # Destination Options for IPv6
rspf 73 RSPF CPHB # Radio Shortest Path First (officially CPHB)
vmtp 81 VMTP # Versatile Message Transport
eigrp 88 EIGRP # Enhanced Interior Routing Protocol (Cisco)
ospf 89 OSPFIGP # Open Shortest Path First IGP
ax.25 93 AX.25 # AX.25 frames
ipip 94 IPIP # IP-within-IP Encapsulation Protocol
etherip 97 ETHERIP # Ethernet-within-IP Encapsulation [RFC3378]
encap 98 ENCAP # Yet Another IP encapsulation [RFC1241]
# 99 # any private encryption scheme
pim 103 PIM # Protocol Independent Multicast
ipcomp 108 IPCOMP # IP Payload Compression Protocol
vrrp 112 VRRP # Virtual Router Redundancy Protocol [RFC5798]
l2tp 115 L2TP # Layer Two Tunneling Protocol [RFC2661]
isis 124 ISIS # IS-IS over IPv4
sctp 132 SCTP # Stream Control Transmission Protocol
fc 133 FC # Fibre Channel
mobility-header 135 Mobility-Header # Mobility Support for IPv6 [RFC3775]
udplite 136 UDPLite # UDP-Lite [RFC3828]
mpls-in-ip 137 MPLS-in-IP # MPLS-in-IP [RFC4023]
manet 138 # MANET Protocols [RFC5498]
hip 139 HIP # Host Identity Protocol
shim6 140 Shim6 # Shim6 Protocol [RFC5533]
wesp 141 WESP # Wrapped Encapsulating Security Payload
rohc 142 ROHC # Robust Header Compression
Those protocol are well defined and standard, I am expecting a windows system to have very similar list.
that somewhat matches that one: https://en.wikipedia.org/wiki/List_of_IP_protocol_numbers
I am kinda new to Python, but I really want to know, what does that mean.
In my book, I have a code:
import socket
import time
HOST = 'data.pr4e.org'
PORT = 80
mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysock.connect((HOST, PORT))
mysock.sendall(b'GET http://data.pr4e.org/cover3.jpg HTTP/1.0\r\n\r\n')
count = 0
picture = b""
while True:
data = mysock.recv(5120)
if len(data) < 1: break
#time.sleep(0.25)
count = count + len(data)
print(len(data), count)
picture = picture + data
mysock.close()
# Look for the end of the header (2 CRLF)
pos = picture.find(b"\r\n\r\n")
print('Header length', pos)
print(picture[:pos].decode())
# Skip past the header and save the picture data
picture = picture[pos+4:]
fhand = open("stuff.jpg", "wb")
fhand.write(picture)
fhand.close()
And the response is:
$ python urljpeg.py
5120 5120
5120 10240
4240 14480
5120 19600
...
5120 214000
3200 217200
5120 222320
5120 227440
3167 230607
Header length 393
HTTP/1.1 200 OK
Date: Wed, 11 Apr 2018 18:54:09 GMT
Server: Apache/2.4.7 (Ubuntu)
Last-Modified: Mon, 15 May 2017 12:27:40 GMT
ETag: "38342-54f8f2e5b6277"
Accept-Ranges: bytes
Content-Length: 230210
Vary: Accept-Encoding
Cache-Control: max-age=0, no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: Wed, 11 Jan 1984 05:00:00 GMT
Connection: close
Content-Type: image/jpeg
I would like to know:
- What do these number in the beginning of the response mean?
- Could anyone recommend a source to read about retrieving image for dummies?
They are the result of
print(len(data), count)
Respectively, the length of the data and the total of data it has received so far.
Since data transfers through a computer network divides the data in packets, you don't receive the whole data at once. Therefore what that code is doing is receiving "chunks" of data and what's printed is the size of the "chunk" and the total amount of data received (by the line print(len(data), count)).
Once all the data has been received, you can extract the picture data. Since you are working with HTTP, the data you receive will be an HTTP response. An HTTP response has two parts a header, which is a series of key-value pairs that give information about the response itself and is what's being printed at the end of your output; and the content which is the data and in your case contains the picture.
In HTTP header and content are separated by two line endings \r\n\r\n. Therefore picture.find(b"\r\n\r\n") looks the position where the header ends and the content (the image) begins.
If all you need to do is retrieve images using HTTP, I would suggest taking a look into the requests package.
Do you know what is going on?
With this code...
import socket
mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysock.connect(('www.py4inf.com', 80))
mysock.send('GET http://www.py4inf.com/code/romeo.txt HTTP/1.0\n\n')
while True:
data = mysock.recv(512)
if ( len(data) < 1 ) :
break
print data;
mysock.close()
I get the correct answer:
%run "c:\users\miguel~1\appdata\local\temp\tmp6uahvi.py"
HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 167
Connection: close
Date: Tue, 30 Aug 2016 14:20:52 GMT
Server: Apache
Last-Modified: Fri, 04 Dec 2015 19:05:04 GMT
ETag: "a7-526172f5b5d89"
Accept-Ranges: bytes
Cache-Control: max-age=604800, public
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: origin, x-requested-with, content-type
Access-Control-Allow-Methods: GET
[... Some random text ...]
The exercise now says to modify the example to be able to connect to pythonlearn.com and read a text file. I don't understand why I get a Bad Request error now...
import socket
mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysock.connect(('www.pythonlearn.com', 80))
mysock.send('GET http://www.pythonlearn.com/code/intro-short.txt HTTP/1.0\n\n')
while True:
data = mysock.recv(512)
if ( len(data) < 1 ) :
break
print data;
mysock.close()
I get a HTTP/1.1 400 Bad Request
HTTP/1.1 400 Bad Request
Date: Tue, 30 Aug 2016 14:31:19 GMT
Connection: close
Set-Cookie: __cfduid=d8fbb6ce8ae7a7163f9bcdb6ffd3c7c681472567479; expires=Wed, 30-Aug-17 14:31:19 GMT; path=/; domain=.pythonlearn.com; HttpOnly
Server: cloudflare-nginx
CF-RAY: 2da8f21c332550fe-MIA
Why? Thanks!
Is there any working example of websocket client on bluemix?
I tried a lot of examples which was found in Github but it is not working. The server is created using node red and an HTML instance is able to communicate with node red server. But, python is not able to communicate.
Here is my code:
ws = create_connection("host name")
print "Sending 'Hello, World'..."
ws.send("Hello, World")
print "Sent"
print "Receiving..."
result = ws.recv()
print "Received '%s'" % result
In the above example, hand shake fails during create connection. I tried many other examples available on internet, but none of them are working.
Edit: Adding more details on handshake problem:
DEBUG:root:--- request header ---
DEBUG:root:GET /ws/Test HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
Host: tryandbuyoncloud.stage1.mybluemix.net
Origin: tryandbuyoncloud.stage1.mybluemix.net
Sec-WebSocket-Key1: 2 0{mN6 9 532X59 5V
Sec-WebSocket-Key2: } pp2B054402V # _-5S8O0 kX
e�8��ۨ-
DEBUG:root:-----------------------
DEBUG:root:--- response header ---
DEBUG:root:HTTP/1.1 500 Error
DEBUG:root:Content-Type: text/plain; charset=UTF-8
DEBUG:root:X-Backside-Transport: FAIL FAIL
DEBUG:root:Connection: close
More details:
487 ws = create_connection("ws://tryandbuyoncloud.stage1.mybluemix.net/ws/Test")
488 print "Sending 'Hello, World'..."
489 ws.send("Hello, World")
<ipython-input-96-f14c8986ac30> in create_connection(url, timeout, **options)
86 websock = WebSocket()
87 websock.settimeout(timeout != None and timeout or default_timeout)
---> 88 websock.connect(url, **options)
89 return websock
90
<ipython-input-96-f14c8986ac30> in connect(self, url, **options)
186 if is_secure:
187 self.io_sock = _SSLSocketWrapper(self.sock)
--> 188 self._handshake(hostname, port, resource, **options)
189
190 def _handshake(self, host, port, resource, **options):
<ipython-input-96-f14c8986ac30> in _handshake(self, host, port, resource, **options)
222 if status != 101:
223 self.close()
--> 224 raise WebSocketException("Handshake Status %d" % status)
225 success, secure = self._validate_header(resp_headers)
226 if not success:
WebSocketException: Handshake Status 500