Class: UPnP::UPnP

Inherits:
Object
  • Object
show all
Defined in:
lib/UPnP.rb

Overview

The UPNP class represent the binding to the library. It exports all the functions the library itself exports.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(autodiscover = true, max_wait = 1000) ⇒ UPnP

This will create a new UPnP instance. max_wait is the maximum time the instance will wait for an answer from the router while seaching or it autodiscover to true will start a thread on the background to scan the network. All the other functions are safe to be called in the meanwhile, they will just wait for the scan to end before operating.



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/UPnP.rb', line 83

def initialize(autodiscover=true,max_wait=1000)
    if max_wait <= 0 then
        raise ArgumentError, "Max wait time must be >= 1."
    end
    if !(autodiscover.is_a? TrueClass) &&
       !(autodiscover.is_a? FalseClass) then
        raise ArgumentError, "Autodiscover must be a boolean value."
    end
    @max_wait_time = max_wait
    # start the discover process at the object initialization.
    # until ruby2, this thread will block the ruby environment
    # for the wait time.
    if autodiscover then
        @igd_thread = Thread.new { discoverIGD }
    else
        @igd_thread = nil
    end
    return nil
end

Instance Attribute Details

#max_wait_timeObject (readonly)

Max time to wait for a broadcast answer from the routers.



75
76
77
# File 'lib/UPnP.rb', line 75

def max_wait_time
  @max_wait_time
end

Instance Method Details

#addPortMapping(nport, lport, proto, desc, client = nil) ⇒ Object

Add a port mapping on the router. Parametes are: network port, local port, description, protocol, ip address to register (or do not specify it to register for yours). Protocol must be Protocol::TCP or Protocol::UDP



316
317
318
319
320
321
322
323
324
325
326
327
# File 'lib/UPnP.rb', line 316

def addPortMapping(nport,lport,proto,desc,client=nil)
    checkProto(proto)
    checkPort(nport)
    checkPort(lport)
    joinThread()
    client ||= @lan if client == nil 
    r = MiniUPnP.UPNP_AddPortMapping(@urls.controlURL,@data.servicetype,
                        nport.to_s,lport.to_s,client,desc,proto)
    if r != 0 then
        raise UPnPException.new , "Failed add mapping: #{code2error(r)}."
    end
end

#connectionTypeObject

Router connection information



185
186
187
188
189
190
191
192
193
# File 'lib/UPnP.rb', line 185

def connectionType()
    joinThread()
    type = getCString()
    if MiniUPnP.UPNP_GetConnectionTypeInfo(@urls.controlURL,
               @data.servicetype,type) != 0 then
        raise UPnPException.new, "Error while retriving connection info."
    end
    type.rstrip
end

#deletePortMapping(nport, proto) ⇒ Object

Delete the port mapping for specified network port and protocol



330
331
332
333
334
335
336
337
338
339
# File 'lib/UPnP.rb', line 330

def deletePortMapping(nport,proto)
    checkProto(proto)
    checkPort(nport)
    joinThread()
    r = MiniUPnP.UPNP_DeletePortMapping(@urls.controlURL,@data.servicetype,
                                       nport.to_s,proto)
    if r != 0 then
        raise UPnPException.new , "Failed delete mapping: #{code2error(r)}."
    end
end

#discoverIGD(max_wait_time = @max_wait_time) ⇒ Object

This method will search for other routers in the network and will wait the specified number of milliseconds that can be ovveridden by the parameter. It has currently (ruby 1.9) a limitation. As long as thread are cooperative the upnpDiscover function will block the ruby implementation waiting for the library. If this will not be solved with ruby 2.0 the interface upnp_wrap.c needs to be hacked. You can avoid to call this function if autodiscover is true. If no router or no UPnP devices are found an UPnPException is thrown.



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/UPnP.rb', line 112

def discoverIGD(max_wait_time=@max_wait_time)
    joinThread()
    if max_wait_time <= 0 then
        raise ArgumentError, "Max wait time must be >= 1"
    end
    @list = MiniUPnP.upnpDiscover(max_wait_time,nil,nil)
    if @list == nil then
        raise UPnPException.new,"No UPNP Device Found"
    end
    define_finalizer(@list,proc {|o| MiniUPnP.freeUPNPDevlist(o)})
    
    @urls = MiniUPnP::UPNPUrls.new
    define_finalizer(@urls,proc {|o| MiniUPnP.FreeUPNPUrls(o)})
    @data = MiniUPnP::IGDdatas.new
    @lan = getCString()

    r = MiniUPnP.UPNP_GetValidIGD(@list,@urls,@data,@lan,64);
    if r == 0 || r == 3 then
        raise UPnPException.new, "No IGD Found"
    end
    @lan = @lan.rstrip()
    return nil
end

#externalIPObject

Returns the external network ip



143
144
145
146
147
148
149
150
151
152
# File 'lib/UPnP.rb', line 143

def externalIP()
    joinThread()
    external_ip = getCString()
    r = MiniUPnP.UPNP_GetExternalIPAddress(@urls.controlURL,
                        @data.servicetype,external_ip)
    if r != 0 then
        raise UPnPException.new, "Error while retriving the external ip address. #{code2error(r)}."
    end
    return external_ip.rstrip()
end

#lanIPObject

Returns the ip of this client



137
138
139
140
# File 'lib/UPnP.rb', line 137

def lanIP()
    joinThread()
    return @lan
end

#maxLinkBitratesObject

Returns the maximum bitrates detected from the router (may be an ADSL router) The result is in bytes/s.



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/UPnP.rb', line 241

def maxLinkBitrates()
    joinThread()
    up, down = 0, 0
    begin
        up_p = MiniUPnP.new_uintp()
        down_p = MiniUPnP.new_uintp()
        if MiniUPnP.UPNP_GetLinkLayerMaxBitRates(@urls.controlURL_CIF,
                                                 @data.servicetype_CIF,
                                                 down_p,up_p) != 0 then
            raise UPnPException.new, "Error while retriving maximum link bitrates."
        end
        up = MiniUPnP.uintp_value(up_p)
        down = MiniUPnP.uintp_value(down_p)
    rescue
        raise
    ensure
        MiniUPnP.delete_uintp(up_p)
        MiniUPnP.delete_uintp(down_p)
    end
    return down,up
end

#portMapping(nport, proto) ⇒ Object

Get the mapping registered for a specific port and protocol



295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
# File 'lib/UPnP.rb', line 295

def portMapping(nport,proto)
    checkProto(proto)
    checkPort(nport)
    if nport.to_i == 0 then
        raise ArgumentError, "Port must be an int value and greater then 0."
    end
    joinThread()
    client = getCString()
    lport = getCString()
    if MiniUPnP.UPNP_GetSpecificPortMappingEntry(@urls.controlURL,
                             @data.servicetype, nport.to_s,proto,
                             client,lport) != 0 then
        raise UPnPException.new, "Error while retriving the port mapping."
    end
    return client.rstrip, lport.rstrip.to_i
end

#portMappingsObject

An array of mappings registered on the router



264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'lib/UPnP.rb', line 264

def portMappings() 
    joinThread()
    i, r = 0, 0
    mappings = Array.new
    while r == 0 
        rhost = getCString()
        enabled = getCString()
        duration = getCString()
        description = getCString()
        nport = getCString()
        lport = getCString()
        duration = getCString()
        client = getCString()
        protocol = getCString()

        r = MiniUPnP.UPNP_GetGenericPortMappingEntry(@urls.controlURL,
                          @data.servicetype,i.to_s,nport,client,lport,
                          protocol,description,enabled,rhost,duration)
        if r != 0 then
            break;
        end
        i = i+1
        mappings << PortMapping.new(client.rstrip,lport.rstrip.to_i,
                          nport.rstrip.to_i,protocol.rstrip,
                          description.rstrip,enabled.rstrip,
                          rhost.rstrip,duration.rstrip)
    end 
    return  mappings
end

#routerIPObject

Returns the ip of the router



155
156
157
158
# File 'lib/UPnP.rb', line 155

def routerIP()
    joinThread()
    @data.urlbase.sub(/^.*\//,"").sub(/\:.*/,"")
end

#statusObject

Returns the status of the router which is an array of 3 elements. Connection status, Last error, Uptime.



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/UPnP.rb', line 162

def status()
    joinThread()
    lastconnerror = getCString()
    status = getCString()
    uptime = 0
    begin
        uptime_uint = MiniUPnP.new_uintp()
        r = MiniUPnP.UPNP_GetStatusInfo(@urls.controlURL,
                   @data.servicetype, status, uptime_uint,
                   lastconnerror) != 0
        if r != 0 then
            raise UPnPException.new, "Error while retriving status info. #{code2error(r)}."
        end
        uptime = MiniUPnP.uintp_value(uptime_uint)
    rescue
        raise
    ensure
        MiniUPnP.delete_uintp(uptime_uint)
    end
    return status.rstrip,lastconnerror.rstrip,uptime
end

#totalBytesReceivedObject

Total bytes received from the external network.



207
208
209
210
211
212
213
214
215
# File 'lib/UPnP.rb', line 207

def totalBytesReceived()
    joinThread()
    v = MiniUPnP.UPNP_GetTotalBytesReceived(@urls.controlURL_CIF,
                @data.servicetype_CIF)
    if v < 0 then
        raise UPnPException.new, "Error while retriving total bytes received."
    end
    return v
end

#totalBytesSentObject

Total bytes sent from the router to external network



196
197
198
199
200
201
202
203
204
# File 'lib/UPnP.rb', line 196

def totalBytesSent()
    joinThread()
    v = MiniUPnP.UPNP_GetTotalBytesSent(@urls.controlURL_CIF,
                @data.servicetype_CIF)
    if v < 0 then
        raise UPnPException.new, "Error while retriving total bytes sent."
    end
    return v
end

#totalPacketsReceivedObject

Total packets received from the router from the external network.



229
230
231
232
233
234
235
236
237
# File 'lib/UPnP.rb', line 229

def totalPacketsReceived()
    joinThread()
    v = MiniUPnP.UPNP_GetTotalBytesSent(@urls.controlURL_CIF,
                @data.servicetype_CIF)
    if v < 0 then
        raise UPnPException.new, "Error while retriving total packets received."
    end
    return v
end

#totalPacketsSentObject

Total packets sent from the router to the external network.



218
219
220
221
222
223
224
225
226
# File 'lib/UPnP.rb', line 218

def totalPacketsSent()
    joinThread()
    v = MiniUPnP.UPNP_GetTotalPacketsSent(@urls.controlURL_CIF,
                @data.servicetype_CIF);
    if v < 0 then
        raise UPnPException.new, "Error while retriving total packets sent."
    end
    return v
end