ようやくだんだんと本題に近づいてきた気がする。では、Go言語入門(9)でやったのと同じようにすすめていく。
mkdir grpctry2
cd grpctry2
mkdir proto
mkdir server
mkdir client
go mod init grpc/grpctry2
そんでもって、protoを書く。こんな感じ。ま~たそれかい的なやつ。
proto/grpctry2.proto
- syntax = "proto3";
- package grpctry2;
- option go_package = "./proto";
- service MyAESEncrypter {
- rpc AESEncrypt (Plain_and_Key) returns (Cipher) {}
- }
-
- message Plain_and_Key {
- bytes plain=1;
- bytes key=2;
- }
-
- message Cipher {
- bytes result=1;
- }
echo $PATH | grep go
ってすれば、PATHが通っていればPATH全体が表示されるし、通ってなければ何も表示されない。
PATHが通ってなければ、
PATH="$PATH:$HOME/go/bin"
ってする。
で、
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative proto/grpctry2.proto
例によって、無言で2つの.pb.goファイルができる。
で、まずはClientを作る。これはGo言語入門(9)のClientのコードをそのまんま持ってきて、.pb.goを見ながら修正していくってかんじ。
client/main.go
- package main
-
- import (
- "context"
- "flag"
- "fmt"
- "log"
- "time"
-
- pb "grpc/grpctry2/proto"
-
- "google.golang.org/grpc"
- "google.golang.org/grpc/credentials/insecure"
- )
-
- var (
- addr = flag.String("addr", "localhost:50051", "the address to connect to")
- )
-
- func main() {
- p := []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}
- k := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}
- flag.Parse()
- // Set up a connection to the server.
- conn, err := grpc.NewClient(*addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
- if err != nil {
- log.Fatalf("did not connect: %v", err)
- }
- defer conn.Close()
- c := pb.NewMyAESEncrypterClient(conn)
-
- // Contact the server and print out its response.
- ctx, cancel := context.WithTimeout(context.Background(), time.Second)
- defer cancel()
- r, err := c.AESEncrypt(ctx, &pb.PlainAnd_Key{Plain: p, Key: k})
- if err != nil {
- log.Fatalf("could not greet: %v", err)
- }
- var res []byte = r.GetResult()
- fmt.Printf("% 02X\n", res)
- }
go get google.golang.org/grpc
cd client
GOOS=windows GOARCH=amd64 go build -o ../grpctry2_client.exe main.go
cd ..
(実行ファイルがプロジェクトルートに出力されるようにした。)
で、とりあえずServer側もGo言語入門(9)のServerのコードをそのまんま持ってきて.pb.goを見ながら修正していく。
server/main.go
- package main
- import (
- "context"
- "flag"
- "fmt"
- "log"
- "net"
-
- pb "grpc/grpctry2/proto"
-
- "google.golang.org/grpc"
- )
-
- var (
- port = flag.Int("port", 50051, "The server port")
- )
-
- // server is used to implement helloworld.GreeterServer.
- type server struct {
- pb.UnimplementedMyAESEncrypterServer
- }
-
- // SayHello implements helloworld.GreeterServer
- func (s *server) AESEncrypt(_ context.Context, in *pb.PlainAnd_Key) (*pb.Cipher, error) {
- var d1 []byte = in.GetPlain()
- var d2 []byte = in.GetKey()
- d3 := []byte{}
- for i := 0; i < 16; i++ {
- d3 = append(d3, d1[i]^d2[i])
- }
-
- return &pb.Cipher{Result: d3}, nil
- }
- func main() {
- flag.Parse()
- lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
- if err != nil {
- log.Fatalf("failed to listen: %v", err)
- }
- s := grpc.NewServer()
- pb.RegisterMyAESEncrypterServer(s, &server{})
- log.Printf("server listening at %v", lis.Addr())
- if err := s.Serve(lis); err != nil {
- log.Fatalf("failed to serve: %v", err)
- }
- }
cd server
GOOS=windows GOARCH=386 go build -o ../grpctry2_server.exe main.go
cd ..
で、実行してみる。
こんな感じで、gPRCを通すことで64bit Windowsアプリから32bit Windowsアプリの機能を実行させることができる。
では、Go言語入門(5)を参考にrijndael.dllを使ってAES暗号化するってのを実装してみる。
server/main.go
- package main
-
- import (
- "context"
- "flag"
- "fmt"
- "log"
- "net"
- "syscall"
- "unsafe"
-
- pb "grpc/grpctry2/proto"
-
- "google.golang.org/grpc"
- )
-
- var (
- hdll, _ = syscall.LoadLibrary("rijndael.dll")
- aes128encrypt, _ = syscall.GetProcAddress(hdll, "AES128Encrypt")
- aes128decrypt, _ = syscall.GetProcAddress(hdll, "AES128Decrypt")
- )
-
- func AES128Encrypt(plain *uint8, key *uint8, crypted *uint8) (r uint32) {
- var nargs uintptr = 3
- ret, _, _ := syscall.Syscall9(uintptr(aes128encrypt),
- nargs,
- uintptr(unsafe.Pointer(plain)),
- uintptr(unsafe.Pointer(key)),
- uintptr(unsafe.Pointer(crypted)),
- 0, 0, 0, 0, 0, 0)
- r = uint32(ret)
- return
- }
- func AES128Decrypt(crypted *uint8, key *uint8, plain *uint8) (r uint32) {
- var nargs uintptr = 3
- ret, _, _ := syscall.Syscall9(uintptr(aes128decrypt),
- nargs,
- uintptr(unsafe.Pointer(crypted)),
- uintptr(unsafe.Pointer(key)),
- uintptr(unsafe.Pointer(plain)),
- 0, 0, 0, 0, 0, 0)
- r = uint32(ret)
- return
- }
-
- var (
- port = flag.Int("port", 50051, "The server port")
- )
-
- type server struct {
- pb.UnimplementedMyAESEncrypterServer
- }
-
- func (s *server) AESEncrypt(_ context.Context, in *pb.PlainAnd_Key) (*pb.Cipher, error) {
- var d1 []byte = in.GetPlain()
- var d2 []byte = in.GetKey()
- var d1arr [16]byte = *(*[16]byte)(d1[:16])
- var d2arr [16]byte = *(*[16]byte)(d2[:16])
- var d3arr [16]byte
- defer syscall.FreeLibrary(hdll)
- AES128Encrypt(&d1arr[0], &d2arr[0], &d3arr[0])
- return &pb.Cipher{Result: d3arr[:]}, nil
- }
- func main() {
- flag.Parse()
- lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
- if err != nil {
- log.Fatalf("failed to listen: %v", err)
- }
- s := grpc.NewServer()
- pb.RegisterMyAESEncrypterServer(s, &server{})
- log.Printf("server listening at %v", lis.Addr())
- if err := s.Serve(lis); err != nil {
- log.Fatalf("failed to serve: %v", err)
- }
- }
こんな感じで、64bit Windows実行ファイルから32bit DLLの実行結果を得ることができる。イイゾ!
フリーアドレスって本当は生産性低下を招いている。って思っている人はどのくらいいるんだろう。固定席なら自然にわかってたことが、あえてヒアリングしないとわからなくなってる。今さら座席を増やす土地やカネがないって目先のことにとらわれてるのならキズが深くなる前に見直してほしい。
defer syscall.FreeLibrary(hdll)
返信削除はAESEncrypt関数内ではダメ。これだと一度AESEncrypt関数が実行されて完了するとDLLが解放されてしまう。main内に入れるのがたぶん良い。