multipeer connectivity advertiser - xcode7

I have a class that implement MCNearbyServiceAdvertiserDelegate. Upon initialization I am able to see the advertised peer from the client if I call MPCManager.advertiser.startadvertisingpeer(). I am trying to implement a method to stop advertising, change the advertiser discoveryInfo and then start advertising again with the new discovery info in place.
The methods sucessfully stop advertising peer but it do not start advertising again. Can you please help me with that
Code details
classMPCManager:NSObject,MCSessionDelegate,MCNearbyServiceBrowserDelegate, MCNearbyServiceAdvertiserDelegate {
var delegate: MPCManagerDelegate?
var session: MCSession!
var sessionList: [MCSession]! = []
var peer: MCPeerID!
var browser: MCNearbyServiceBrowser!
var advertiser: MCNearbyServiceAdvertiser!
var foundPeers:[NSDictionary]! = []
var invitationHandler: ((Bool, MCSession!)->Void)!
var discoveryInfo:[String: String]!
init(discoveryInfo:[String:String]!, peer:MCPeerID!) {
super.init()
self.discoveryInfo = discoveryInfo
self.peer = peer
session = MCSession(peer: self.peer)
session.delegate = self
browser = MCNearbyServiceBrowser(peer: peer, serviceType: "myservicetype")
browser.delegate = self
advertiser = MCNearbyServiceAdvertiser(peer: self.peer, discoveryInfo: self.discoveryInfo, serviceType: "myservicetype")
advertiser.delegate = self
}
/////some other methods
///the problematic method
func setAdvertising(discoveryInfo:[String:String]!){
print("setting advertising")
self.discoveryInfo = discoveryInfo
advertiser.stopAdvertisingPeer()
advertiser = nil
self.advertiser = MCNearbyServiceAdvertiser(peer: self.peer, discoveryInfo: self.discoveryInfo, serviceType: "myservicetype")
self.advertiser.delegate = self
print("advertising from set advertising")
advertiser.startAdvertisingPeer()
}

Finally get it work. I sought in another posts to use discovery info as dictionary instead of [String:String] strange thing but its working now :D!. Thanks all that take time to read

Related

gsutil on a Google Compute Engine VM can't use service account authentication with a key file

I'm launching an instance from the google .net API and despite my best efforts I can't get it to copy anything to or from storage. Currently I'm authenticating with a developer console service account like this:-
string ServiceAccountEmail = "blahblah#developer.gserviceaccount.com";
var certificate = new X509Certificate2(#"key.p12", "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(ServiceAccountEmail)
{
Scopes = new[] { ComputeService.Scope.Compute, ComputeService.Scope.DevstorageFullControl }
}.FromCertificate(certificate));
var cs = new ComputeService(new BaseClientService.Initializer
{
ApplicationName = "appname",
HttpClientInitializer = (Google.Apis.Http.IConfigurableHttpClientInitializer)credential,
});
Google.Apis.Compute.v1.Data.Instance newinst = new Google.Apis.Compute.v1.Data.Instance();
newinst.Name = "generatedinstance";
newinst.MachineType = "https://www.googleapis.com/compute/v1/projects/projectid/zones/zone/machineTypes/n1-standard-1";
Google.Apis.Compute.v1.Data.AttachedDisk ad = new Google.Apis.Compute.v1.Data.AttachedDisk();
ad.AutoDelete = true;
ad.Boot = true;
ad.Type = "PERSISTENT";
ad.InitializeParams = new Google.Apis.Compute.v1.Data.AttachedDiskInitializeParams();
ad.InitializeParams.DiskName = "newdisk";
ad.InitializeParams.SourceImage = "https://www.googleapis.com/compute/v1/projects/projectid/global/images/customimage";
ad.InitializeParams.DiskType = "https://www.googleapis.com/compute/v1/projects/projectid/zones/zone/diskTypes/pd-standard";
ad.Mode = "READ_WRITE";
newinst.Disks = new List<Google.Apis.Compute.v1.Data.AttachedDisk>();
newinst.Disks.Add(ad);
Google.Apis.Compute.v1.Data.NetworkInterface ni = new Google.Apis.Compute.v1.Data.NetworkInterface();
ni.Network = "https://www.googleapis.com/compute/v1/projects/projectid/global/networks/default";
ni.AccessConfigs = new List<Google.Apis.Compute.v1.Data.AccessConfig>();
ni.AccessConfigs.Add(new Google.Apis.Compute.v1.Data.AccessConfig
{
Type = "ONE_TO_ONE_NAT",
Name = "External NAT",
});
newinst.NetworkInterfaces = new List<Google.Apis.Compute.v1.Data.NetworkInterface>();
newinst.NetworkInterfaces.Add(ni);
var start = new Google.Apis.Compute.v1.Data.Metadata.ItemsData();
start.Key = "startup-script";
start.Value = "*startup script* includes gsutil cp which won't work without service account attached";
newinst.Metadata = new Google.Apis.Compute.v1.Data.Metadata();
newinst.Metadata.Kind = "compute#metadata";
newinst.Metadata.Items = new List<Google.Apis.Compute.v1.Data.Metadata.ItemsData>();
newinst.Metadata.Items.Add(start);
newinst.ServiceAccounts = new List<Google.Apis.Compute.v1.Data.ServiceAccount>();
//var sa = new Google.Apis.Compute.v1.Data.ServiceAccount();|with this section
//sa.Email = "blahblah#developer.gserviceaccount.com"; |the instance won't
//sa.Scopes = new[] { ComputeService.Scope.Compute, |start. (An equivalent
ComputeService.Scope.DevstorageFullControl }; |is found in instance
//newinst.ServiceAccounts.Add(sa); |start REST request)
var instinsert = new InstancesResource.InsertRequest(cs, newinst, "projectid", "zone");
var insertresponse = instinsert.Execute();
The message I get when I try to use gsutil cp is "You do not currently have an active account selected.". Can anyone tell me where I'm going wrong?
You need to run gcloud auth activate-service-account blahblah#developer.gserviceaccount.com --key-file path_to_key.p12 to tell the Cloud SDK (including gsutil) about your service account.
As per the code provided, I can see that the original example has
var certificate = new X509Certificate2(#"key.p12", "notasecret", X509KeyStorageFlags.Exportable);
I notice you are missing the '#'in your code. I'm not very familiar with .Net. I have tested these examples in python and this one. When creating my instance I added the service account for GCS and the file is uploaded correctly.
OKAY! Problem solved. The part I was getting wrong was the bit commented out in the question-
var sa = new Google.Apis.Compute.v1.Data.ServiceAccount();
sa.Email = "blahblah#developer.gserviceaccount.com";
sa.Scopes = new[] { ComputeService.Scope.Compute,
ComputeService.Scope.DevstorageFullControl };
newinst.ServiceAccounts.Add(sa);
I needed the email for the main service account for the developer console in this section rather than the same service account I used to create the credentials but don't ask me why. Point is the instance launches and gsutil is now happily copying away.
Thanks for your time and help everyone!
Ross

How to access contacts API with Service Account

I am in the process of upgrading my Marketplace applications to support the new marketplace api and OAUTH 2.
I have managed to migrate most APIs but am stuck on the contacts api. With the the previous marketplace version we used 2LO and client key/client secret to authenticate across the Google Apps domain. My understanding is that the only way to do this in current version is with Service Accounts and OAuth 2.
Based on the V3 calendar API I'm assuming something like this (although the contacts API does not support it from what I can see) -
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { "https://www.google.com/m8/feeds" },
User = "admin#domain.co"
}.FromCertificate(certificate));
var service = new ContactsService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Contact API Sample",
});
If anybody has done this, your advice will be appreciated!
I know this question has been answered, but adding an alternative that doesn't require the AssertionFlowClient or a specific version of DotNetOpenAuth. This allows you to use the same ServiceAccountCredential code from your original question (ie, using the same method to query a user's gmail)
Thank you for following up on your own post, it helped me find this solution!
private static ServiceAccountCredential GenerateCred(IEnumerable<string> scopes, string delegationUser)
{
var certificate = new X509Certificate2(certLocation, certPassword, X509KeyStorageFlags.Exportable);
var credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = scopes,
User = delegationUser
}.FromCertificate(certificate));
return credential;
}
var credential = GenerateCred(new[] { "https://www.googleapis.com/auth/contacts.readonly" }, userToDelegate);
//Get the token for this scope and user
await credential.RequestAccessTokenAsync(new CancellationToken());
//use the token to initalize the request
var rs = new RequestSettings(projectName)
{
OAuth2Parameters = new OAuth2Parameters()
{
AccessToken = credential.Token.AccessToken
}
};
var request = new ContactsRequest(rs);
Feed<Contact> f = request.GetContacts();
foreach (var c in f.Entries)
{
//process each contact
}
Well I got no response anywhere on this so I can only assume that the standard client libraries don't have support for this.
I have come up with a workaround based on the following post for email access.
http://www.limilabs.com/blog/oauth2-gmail-imap-service-account
You will need to follow his post and note the following:
this must use the DotNetOpenAuth version that he specifies. The latest version will not work.
You will only need his AssertionFlowClient classes which can be added to the below code I have provided here:
X509Certificate2 certificate = new X509Certificate2(
serviceAccountCertPath,
serviceAccountCertPassword,
X509KeyStorageFlags.Exportable);
AuthorizationServerDescription server = new AuthorizationServerDescription
{
AuthorizationEndpoint = new Uri("https://accounts.google.com/o/oauth2/auth"),
TokenEndpoint = new Uri("https://accounts.google.com/o/oauth2/token"),
ProtocolVersion = ProtocolVersion.V20,
};
AssertionFlowClient provider = new AssertionFlowClient(server, certificate)
{
ServiceAccountId = serviceAccountEmail,
Scope = string.Join(" ", new[] { "https://mail.google.com/", "https://www.google.com/m8/feeds/" }),
ServiceAccountUser = userEmail,
};
IAuthorizationState grantedAccess = AssertionFlowClient.GetState(provider);
RequestSettings rs = new RequestSettings("iLink");
rs.OAuth2Parameters = new OAuth2Parameters();
rs.OAuth2Parameters.AccessToken = grantedAccess.AccessToken;
rs.OAuth2Parameters.RefreshToken = null;
rs.OAuth2Parameters.ClientId = null;
rs.OAuth2Parameters.ClientSecret = null;
rs.OAuth2Parameters.RedirectUri = null;
ContactsRequest cr = new ContactsRequest(rs);
Feed<Contact> f = cr.GetContacts();
foreach (var c in f.Entries)
{
Response.Write(c.Name.FullName);
}

Google Chrome Indexdb - redundant code

I am tryint yo understand some code from an opensource project that handles indexDB commands within a Google Chrome application.
The code is as follows :
var db = pm.indexedDB.db;
var trans = db.transaction([pm.indexedDB.TABLE_DRIVE_CHANGES], "readwrite");
var store = trans.objectStore(pm.indexedDB.TABLE_DRIVE_CHANGES);
var boundKeyRange = IDBKeyRange.only(driveChange.id);
var request = store.put(driveChange);
request.onsuccess = function (e) {
callback(driveChange);
};
request.onerror = function (e) {
console.log(e.value);
};
Although the app works, to me it seems that the following line is redundant code
var boundKeyRange = IDBKeyRange.only(driveChange.id);
Or am I missing something? The variable 'boundKeyRange' is never referenced anywhere.
Unless boundKeyRange is used later, you're not missing something. IDBKeyRange.only just creates an IDBKeyRange object, and if that object isn't used in some IndexedDB request, it does absolutely nothing.

Google cast: How to show metadata in default media player?

I am trying to make my chrome sender application send metadata to the default media receiver application but the default media receiver does not show the metadata. I cannot find documentation or examples. Does anybody know how implement this? Below code plays the audio but the player does not show any image or other metadata.
Initialization:
var sessionRequest = new chrome.cast.SessionRequest(chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID);
var apiConfig = new chrome.cast.ApiConfig(sessionRequest,
sessionListener,
receiverListener);
chrome.cast.initialize(apiConfig, onInitSuccess, onError);
chrome.cast.requestSession(onRequestSessionSuccess, onLaunchError);
...
Loading media
url = "url-to-media"
var mediaInfo = new chrome.cast.media.MediaInfo(url, 'audio/aac');
mediaInfo.metadata = new chrome.cast.media.MusicTrackMediaMetadata()
mediaInfo.metadata.albumName = 'This is the name of the album'
mediaInfo.metadata.artistName = 'This is the name of the artist'
mediaInfo.metadata.songName = 'This is the name of the song'
im = chrome.cast.Image('http://m1.behance.net/rendition/modules/575407/disp/822271229466847.png')
mediaInfo.metadata.images = new Array(im)
var request = new chrome.cast.media.LoadRequest(mediaInfo);
session.loadMedia(request,onMediaDiscovered.bind(this, 'loadMedia'), onMediaError())
Try this -
mediaInfo.metadata.title = 'This is the name of the song';
mediaInfo.metadata.subtitle = 'This is the name of the artist';
We've just released a Cast extension Beta that has fixed this issue. See this announcement: https://plus.google.com/+ShawnShen/posts/aVXSHyceNbR.
I also added a project on github that provides sample code at:
https://github.com/googlecast/CastMedia-chrome
Currently the default media receiver app accepts certain metadata fields. Detailed specs are given here: https://developers.google.com/cast/docs/reference/messages.
For the MusicTrackMediaMetaData type, be sure to set metadataType to 3. The following snippet works.
mediaInfo.metadata = new chrome.cast.media.MusicTrackMediaMetadata()
mediaInfo.metadata.metadataType = 3;
mediaInfo.metadata.title = 'This is the name of the title';
mediaInfo.metadata.albumArtist = 'This is the name of the album artist';
mediaInfo.metadata.artist = 'This is the name of the artist';
mediaInfo.metadata.albumName = 'This is the name of the album';
//mediaInfo.metadata.composer = 'composer';
//mediaInfo.metadata.trackNumber = 13;
//mediaInfo.metadata.discNumber = 2;
mediaInfo.metadata.releaseDate = '2011';
mediaInfo.metadata.images = [{'url': 'http://m1.behance.net/rendition/modules/575407/disp/822271229466847.png'}];
var request = new chrome.cast.media.LoadRequest(mediaInfo);
session.loadMedia(request, onMediaDiscovered.bind(this, 'loadMedia'), onMediaError());
A bug has been filed to fix some mismatch between Chrome Sender SDK and default receiver app.
You can always do your own custom receiver app and add your own custom data like the following.
var mediaInfo = new chrome.cast.media.MediaInfo(url, 'audio/mp3');
var request = new chrome.cast.media.LoadRequest(mediaInfo);
var payload = {
"albumName": 'This is the name of the album',
"songName": 'This is the name of the song',
"thumb": 'http://m1.behance.net/rendition/modules/575407/disp/822271229466847.png',
"artistName": 'This is the name of the artist'
};
var json = {
"payload": payload
};
request.customData = json;

How to uniquely identify a socket with Node.js

TLDR; How to identify sockets in event based programming model.
I am just starting up with node.js , in the past i have done most of my coding
part in C++ and PHP sockets() so node.js is something extremely new to me.
In c++ to identify a socket we could have done something like writing a main socket say server to listen for new connections and changes, and then handling those connections accordingly.
If you are looking for actual sockets and not socket.io, they do exist.
But as stated, Node.js and Javascript use an event-based programming model, so you create a (TCP) socket, listen on an IP:port (similar to bind), then accept connection events which pass a Javascript object representing the connection.
From this you can get the FD or another identifier, but this object is also a long-lived object that you can store an identifier on if you wish (this is what socket.io does).
var server = net.createServer();
server.on('connection', function(conn) {
conn.id = Math.floor(Math.random() * 1000);
conn.on('data', function(data) {
conn.write('ID: '+conn.id);
});
});
server.listen(3000);
Timothy's approach is good, the only thing to mention - Math.random() may cause id's duplication. So the chance it will generate the same random number is really tiny, but it could happen. So I'd recommend you to use dylang's module - shortid:
var shortid = require('shortid');
var server = net.createServer();
server.on('connection', function(conn) {
conn.id = shortid.generate();
conn.on('data', function(data) {
conn.write('ID: '+conn.id);
});
});
server.listen(3000);
So in that case you can be sure that no id duplications will occur.
in typescript:
import { v4 as uuidv4 } from 'uuid';
import net from 'net';
class Socket extends net.Socket {
id?: string;
}
const server = net.createServer();
server.on('connection', (conn) => {
conn.id = uuidv4();
conn.on('data', (data) => {
console.log(conn.id);
});
});
server.listen(3000);
you need to add id first;
In c++ to identify a socket we could have done something like writing
a main socket say server to listen for new connections and then
handling those connections accordingly.but so far i havent found
anything like that in node.js . (the berkeley socket model) Does it
even exist in node.js .. if not i am going back to my C++ :$
You should go back, because JavaScript is a prototype-based, object-oriented scripting language that is dynamic, weakly typed and has first-class functions. They are both completely different languages and you will have to have a different mindset to write clean JavaScript code.
https://github.com/LearnBoost/Socket.IO/wiki/Migrating-0.6-to-0.7
Session ID
If you made use of the sessionId property of socket in v0.6, this is now simply .id.
// v0.6.x
var sid = socket.sessionId;
// v0.7.x
var sid = socket.id;
if you found this question by looking for socket.io unique ids that you can use to differentiate between sockets on the client-side (just like i did), then here is a very simple answer:
var id = 0; //initial id value
io.sockets.on('connection', function(socket) {
var my_id = id; //my_id = value for this exact socket connection
id++; //increment global id for further connnections
socket.broadcast.emit("user_connected", "user with id " + my_id + "connected");
}
on every new connection the id is incremented on the serverside. this guarantees a unique id.
I use this method for finding out where a broadcast came from on the clientside and saving data from concurrent sockets.
for example:
server-side
var my_coords = {x : 2, y : -5};
socket.broadcast.emit("user_position", {id: my_id, coord: my_coords});
client-side
user = {};
socketio.on("user_position", function(data) {
if(typeof user[data.id] === "undefined")
user[data.id] = {};
user[data.id]["x"] = data.coord.x;
user[data.id]["y"] = data.coord.y;
});
How to identify a client based on its socket id. Useful for private messaging and other stuff.
Using socket.io v1.4.5
client side:
var socketclientid = "john"; //should be the unique login id
var iosocket = io.connect("http://localhost:5000", {query: "name=john"});
var socketmsg = JSON.stringify({
type: "private messaging",
to: "doe",
message: "whats up!"
});
iosocket.send(socketmsg);
server side:
io.on('connection', function(socket){
var sessionid = socket.id;
var name = socket.handshake.query['name'];
//store both data in json object and put in array or something
socket.on('message', function(msg){
var thesessionid = socket.id;
var name = ???? //do lookup in the user array using the sessionid
console.log("Message receive from: " + name);
var msgobject = JSON.parse(msg);
var msgtype = msgobject.type;
var msgto = msgobject.to;
var themessage = msgobject.message;
//do something with the msg
//john want to send private msg to doe
var doesocketid = ???? //use socket id lookup for msgto in the array
//doe must be online
//send to doe only
if (msgtype == "private messaging")
socket.to(doesocketid).emit('message', 'themessage');
});
mmmm, i don't really get what you're looking for but socket-programming with node.js (and socket.io) is really straight forward. take a look at some examples on the socket.io homepage:
// note, io.listen() will create a http server for you
var io = require('socket.io').listen(80);
io.sockets.on('connection', function (socket) {
io.sockets.emit('this', { will: 'be received by everyone connected'});
socket.on('private message', function (from, msg) {
console.log('I received a private message by ', from, ' saying ', msg);
});
socket.on('disconnect', function () {
sockets.emit('user disconnected');
});
});
on connecting to the server, every socket get an unique id with which you can identify it later on.
hope this helps!?
cheers